Cuando solc crea código para matrices cuando se declaran public
. En particular, contiene una verificación de la longitud de la matriz. Por ejemplo, esto:
contract OutOfBoundsException {
uint256[8] public array;
}
compilado con solc --optimize
produce:
...
tag_3:
pop
/* "contracts/oobtest.sol":46:68 uint256[8] public array */
tag_4
calldataload(0x4)
jump(tag_5)
tag_4:
# dead code
tag_5:
0x0
dup1
sload
dup3
swap1
dup2
lt
tag_6
jumpi
invalid
tag6
# ...
La --optimize
bandera se usó para eliminar parte de la basura y simplificar algo de lo anterior.
¿Qué está pasando en el bloque básico que comienza tag_5
y por qué es necesario?
La respuesta corta: ese código se usaría si el contrato hubiera intentado acceder array
usando una función de acceso. Pero solc
no es lo suficientemente inteligente como para darse cuenta de que eso no puede suceder aquí y en muchas otras situaciones como esta.
Aquí hay una situación en la que se necesita esta verificación:
contract PublicArray {
uint256[8] public array;
}
contract InvalidAccess {
PublicArray array_contract;
constructor() {
array_contract = PublicArray.at(0x(...))
}
function go() {
return array_contract.array[1000];
}
}
Esta información y el código anterior son del famoso Bernhard Mueller .
Dado que array
es público, solc
crea una función de acceso para él.
tag3
es el comienzo de esa función. calldataload(0x4)
carga el índice de calldata, luego tag_5
hay una verificación de que calldataload(0x4)
< array.length
.