¿Hay alguna falla en mi contrato de solidez?

Imagine un contrato simple que cobra Eth. ¿Hay alguna forma de manipular esto de manera que después de que los usuarios envíen fondos, this.balance =/= max_val? ¿Se puede jugar esto de una manera que permita que isFinished() nunca pueda pasar la instrucción require?

uint max_val = 3 * 10** 18; // Can send up to 3 ETH
bool finished = false; // Not finished

// Function to send ETH
function sendEth() payable {
    require(!finished); // Cannot be over
    require(this.balance <= max_val);  // Contribution must be less than or equal to contribution max
}

// Function to finish sending
function isFinished() {
    require(!finished); // Cannot be finished. Cannot be called twice.
    require(this.balance == max_val);  // Must have collected max ETH
    finished = true;
}

Respuestas (2)

Un par de comentarios primero:

  1. ¿Por qué la función que recibe ether se llama sendEth? ¿No debería llamarse receiveEthporque eso es lo que hace?
  2. ¿Por qué no usar modificadores que hagan que su código sea significativamente más fácil de entender? Código fácil de entender == código con menos errores.

Supongo que el saldo se actualiza después de la función, pero no estoy seguro (ver el comentario a continuación).

pragma solidity ^0.4.11;

contract Testing {

    uint max_val = 3 * 10 ** 18;
    bool finished = false;

    modifier notFinished() {
       if (finished)
           revert();
       _;
    }

    // NOTE: Not sure if this.balance is already updated with
    // the new msg.value (my guess is no). I will edit this code
    // if someone corrects me.
    function receiveEth() notFinished() payable {

       // If the tx would go over max, revert
       if (msg.value + this.balance > max_val)
           revert();

       // If we will have exactly max, we're done
       if (msg.value + this.balance == max_val)
           finished = true;

       // Otherwise, accept the eth
    }
}

A juzgar por su código, es trivial enviar más que max_valporque no verifica si msg.valuees más que max_value - this.balance. Necesitas agregar require(msg.value <= max_value - this.balance)adentro sendEth().

Tengo entendido que justo cuando sendEth()se llama, this.balancese actualiza, antes de pasar por cualquier línea de la función. Si este es el caso, ¿entonces no require(msg.value <= max_value - this.balance)sería redundante?
Creo que el saldo se actualiza después, pero no puedo encontrarlo en los documentos.