Transferencia ERC20: la persona que llama espera una devolución pero no se proporciona ninguna, ¿qué sucede?

Si alguien implementa la función transfer() ERC20 sin el valor de retorno de la siguiente manera:

function transfer(address to, uint256 value) public {
    require( ... usual checks ... );
    balances_[msg.sender] -= value;
    balances_[to] += value;

    emit Transfer(to, value);
}

Pero un contrato de llamada espera el valor de retorno:

  function transfer(address to, uint256 value) public returns (bool)

y llama a la función de alguna manera como:

ERC20 token = (ERC20)someaddress;
if (!token.transfer(to,amt)) { ... }

Suponiendo someaddressque es correcto, ¿qué sucede?

Me imagino que la función de transferencia funcionaría bien pero no devolvería nada, lo que haría que la persona que llama recibiera un falso . Se actualizarían los saldos y se emitiría un evento.

¿Estoy en lo correcto? ¿Fracasaría la llamada? ¿Alguna excepción?

¡Gracias!

Respuestas (1)

El Libro Amarillo proporciona la respuesta. Y la respuesta es que el comportamiento es indefinido e imprevisible. La llamada no fallará, por lo que se transferirán tokens, pero no se puede confiar en el valor de retorno y no está definido (en el sentido de que, en el caso general, no podemos predecir cuál será).

La segunda imagen a continuación muestra que la memoria de la persona que llama (el contrato inteligente que realiza la llamada al otro contrato) no se actualizará con esta llamada de función. Entonces, la persona que llama leerá de una parte de su propia memoria que puede ser cero y puede ser cualquier otra cosa y lo evaluará como un valor booleano, el valor devuelto, lo que significa que será falso si la memoria no se declaró previamente o se estableció en cero. , y que será cierto si esa parte de la memoria se estableció en un valor distinto de cero, pero el compilador determinó que ese valor distinto de cero ya no era necesario.

Definición de los datos de salida

Parte de la definición del código de operación CALL
Esta última imagen muestra una parte de la definición del código de operación CALL. µ[5]indica el inicio de la memoria donde se almacenará el resultado de la persona que llama, µ[6]es el tamaño de salida que espera la persona que llama y, nen nuestro caso, es el tamaño de la salida de la persona que llama, que es 0. Por lo tanto, no hay memoria en la VM de la persona que llama se actualizará para que la persona que llama simplemente lea lo que está presente en la ubicación µ[5]de la memoria µ[5]+µ[6]antes de que se realice la llamada e interprete eso como el valor de retorno. Creo que este valor será en la mayoría de los casos (¿todos?) 0x0 (falso), por lo que la persona que llama interpretará el resultado del destinatario como falso.

No he ejecutado este código, solo he deducido la respuesta. Si quiere estar seguro de que esta respuesta es correcta, debe realizar algunas pruebas usted mismo o esperar que alguien más inteligente que yo responda :)