Cuando compilo un contrato en blanco:
contract A {}
con
solc --optimize --optimize-runs 300000 --opcodes test.sol
Yo obtengo:
PUSH1 0x60 PUSH1 0x40 MSTORE PUSH1 0x6 DUP1 PUSH1 0x10 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN PUSH1 0x60 PUSH1 0x40 MSTORE STOP
¿Qué es? Según tengo entendido, este código de bytes no es el código del contrato, sino el código que durante la ejecución genera el contrato. Pero no entiendo lo que está pasando.
Probablemente
PUSH1 0x60 PUSH1 0x40 MSTORE
es un patrón para asignar 64 bytes (0x40) en la memoria. En caso afirmativo, ¿por qué necesitamos asignarlo manualmente?
Hay algunas líneas en papel amarillo sobre la separación de 'código' y 'datos'. Puedo verlo, cuando se ejecuta solc
con --asm-json
. Pero, ¿cómo interactúan realmente estas dos partes?
Siento que me perdí un papel o manual muy importante donde se aclara todo. ¿Dónde puedo conseguirlo?
Para resumir:
code
y las data
secciones del contrato?La sección de "datos" mencionada en el papel amarillo es la parte que sigue a la instrucción PUSH, es decir, el papel amarillo solo habla de datos de inserción. Lo que ve en la salida del ensamblaje es un concepto de nivel superior.
El (código de inicio del) contrato en blanco copia el código de contrato final del código a la memoria y luego lo devuelve.
Tanto el código de contrato final como el código de inicio comienzan almacenando el llamado "puntero de memoria libre" en la posición de memoria 0x40. Este puntero le indica dónde se puede asignar el siguiente fragmento de memoria libre. En el caso de este contrato, esto es totalmente innecesario y probablemente se optimizará en la siguiente fase de mejora del optimizador.
Un usuario de Reddit publicó amablemente un análisis de código de operación por código de operación para usted:
PUSH1 0x60 PUSH1 0x40 MSTORE
Almacene 0x60 en la ubicación de memoria 0x40. Creo que esto se usa normalmente para la indexación de variables si tiene una. Nunca he entrado en detalles de esto.
PUSH1 0x6 DUP1
Inserte 2 valores de 0x6 en la pila. Uno se debe usar como parámetro para CODECOPY, el otro se debe usar como parámetro para RETURN. Este es el tamaño del cuerpo de su código. Consiste en PUSH1 0x60 PUSH1 0x40 MSTORE (nuevamente indexación variable) STOP (se explica por sí mismo).
EMPUJAR 0x10
Este es un parámetro de CODECOPY. Se refiere al desplazamiento donde se encuentra el código que se va a copiar en la memoria. Básicamente, el cuerpo de su código (la parte no constructora).
EMPUJAR1 0x0
Parámetro de CODECOPIA. Se refiere a qué memoria compensa el código que se va a copiar.
CODECOPIA
Copie parte del código en la memoria. Según el parámetro que le hemos dado, solicita copiar 6 bytes desde el desplazamiento del byte 17 (si cuenta desde 1) en la ubicación de memoria 0.
EMPUJAR 0x0 VOLVER
RETURN toma dos parámetros, el número de bytes a devolver y el desplazamiento en memoria a devolver. Dado que estamos creando un contrato, este es el código que pretendemos cargar. Así que tenemos 6 bytes (del DUP1 anterior), que es el tamaño y 0 (compensación de memoria en la que copiamos el código anterior).
q9f