在读取https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html#abi时,我只是在想,当回调数据包含比函数预期更多的参数/数据时会发生什么(我知道第一个参数是函数签名的4字节Keccak256,所以这不可能是偶然发生的)。只是您可以使用任意的msg.data。我认为那些exta字节应该被默默地忽略(从未被引用),还是我弄错了?这意味着完全相同的函数调用可以用许多不同的方式进行编码。
此外:如果动态数组“偏移”点位于给定参数之外(或大小大于实际提供值的数量),会发生什么情况。你能想象所有未定义的东西都是0,还是会抛出一个异常?
发布于 2019-01-24 20:07:57
是的,额外的调用数据字节将被忽略,是的,在长度结束后读取的回调数据是0。
发布于 2019-01-24 20:49:46
添加smarx的答案(忽略额外的调用数据):
此外:如果动态数组“偏移”点位于给定参数之外(或大小大于实际提供值的数量),会发生什么情况。你能想象所有未定义的东西都是0,还是会抛出一个异常?
对于字节/字符串/数组等动态大小对象,如果大小大于调用数据中提供的值的数量,则将得到一个还原。
您可以使用以下代码在Remix中自己测试这一点:
pragma solidity ^0.5.0;
contract X {
event E(bytes data);
function b(bytes memory _b) public {
emit E(msg.data);
}
}
contract Test {
event E(bytes data);
X x = new X();
function b(bytes memory _b) public payable {
emit E(msg.data);
// shorten calldata by 30 bytes
bytes memory callData = new bytes(msg.data.length-30);
for(uint i=0; i<callData.length && i<msg.data.length; i++) {
callData[i] = msg.data[i];
}
// this will work fine as long as _b.length <= 2
(bool res, bytes memory ret) = address(x).call(callData);
assert(res);
}
}发布于 2019-01-26 14:25:03
我深入研究了EVM字节码,发现它显式地检查CALLDATASIZE。另外,非付费函数获得自动编译的if (msg.value != 0)恢复。因此,要回答我自己的问题--如果您只是读取任何(未初始化的)内存,您将得到0,但是对于生成的函数Solidity编译器,似乎会自动添加在LT (低于)情况下进行还原的检查(如果有太多的数据,什么都不会发生)。因此,稳健性本身就可以确保参数的某些条件不变,因此没有其他的魔力。
https://ethereum.stackexchange.com/questions/66070
复制相似问题