Este contrato trivial:
contract Test {
function test() returns (string) {
return "foobar";
}
}
Da como resultado una salida de código ensamblador (en el compilador web solidity) para la función 'prueba' que se ve así:
tag 2 function test() returns (strin...
JUMPDEST function test() returns (strin...
PUSH 0 contract Test {\n function ...
PUSH 60 contract Test {\n function ...
MSTORE string
PUSH C0 return "foobar"
PUSH 40 contract Test {\n function ...
MSTORE return "foobar"
PUSH 6 return "foobar"
PUSH 80 string
SWAP1 return "foobar"
DUP2 return "foobar"
MSTORE return "foobar"
PUSH 666F6F6261720000000000000000000000000000000000000000000000000000 return "foobar"
PUSH A0 return "foobar"
MSTORE return "foobar"
PUSH 20 string
PUSH C0 return "foobar"
SWAP1 function test() returns (strin...
DUP2 function test() returns (strin...
MSTORE function test() returns (strin...
PUSH 6 return "foobar"
PUSH E0 function test() returns (strin...
DUP2 function test() returns (strin...
SWAP1 function test() returns (strin...
MSTORE function test() returns (strin...
DUP2 return "foobar"
SWAP1 return "foobar"
PUSH 100 function test() returns (strin...
SWAP1 function test() returns (strin...
PUSH A0 return "foobar"
SWAP1 return "foobar"
DUP1 return "foobar"
DUP4 function test() returns (strin...
DUP2 return "foobar"
DUP5 return "foobar"
PUSH 0 contract Test {\n function ...
PUSH 4 function test() returns (strin...
PUSH 12 function test() returns (strin...
CALL function test() returns (strin...
POP
POP
DUP2 function test() returns (strin...
MLOAD function test() returns (strin...
PUSH FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
NOT
AND function test() returns (strin...
SWAP1 function test() returns (strin...
SWAP2 function test() returns (strin...
MSTORE function test() returns (strin...
POP
POP
PUSH 40 contract Test {\n function ...
MLOAD function test() returns (strin...
PUSH 120 function test() returns (strin...
DUP2 function test() returns (strin...
SWAP1 function test() returns (strin...
SUB function test() returns (strin...
SWAP3 function test() returns (strin...
POP
SWAP1 function test() returns (strin...
POP
RETURN
Puedo ver que la versión hexadecimal de la cadena y su longitud se escriben en la memoria desde el principio. Luego hace un montón de cosas raras y emite una LLAMADA con muy poca gasolina para dirigirse a '4', por lo que puedo decir. El documento amarillo de Ethereum dice que el contrato en la dirección 4 implementa la función de identidad, lo que parece algo completamente inútil en este contexto.
¿Por qué está haciendo esto para lo que parece un 'retorno' muy sencillo?
Al discutir con los desarrolladores de Solidity en Gitter, esto queda claro: Solidity usa la función de identidad como una operación barata memcpy
, y el optimizador no es lo suficientemente inteligente actualmente como para darse cuenta de que solo puede cargar la cadena literal en la memoria como la totalidad de la valor de retorno Por lo tanto, carga la cadena en la memoria, usa la función de identidad para copiarla en la ubicación de retorno y luego la devuelve.
El código ensamblador incluye todas las funciones requeridas para crear el contrato de las cuales la identificación es una, es decir, el contrato tiene que ser identificable. La función de 'prueba' real no usa todas las funciones en el código ensamblador.
ética