首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >参数太多的Calldata

参数太多的Calldata
EN

Ethereum用户
提问于 2019-01-24 12:47:34
回答 3查看 1.5K关注 0票数 1

在读取https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html#abi时,我只是在想,当回调数据包含比函数预期更多的参数/数据时会发生什么(我知道第一个参数是函数签名的4字节Keccak256,所以这不可能是偶然发生的)。只是您可以使用任意的msg.data。我认为那些exta字节应该被默默地忽略(从未被引用),还是我弄错了?这意味着完全相同的函数调用可以用许多不同的方式进行编码。

此外:如果动态数组“偏移”点位于给定参数之外(或大小大于实际提供值的数量),会发生什么情况。你能想象所有未定义的东西都是0,还是会抛出一个异常?

EN

回答 3

Ethereum用户

回答已采纳

发布于 2019-01-24 20:07:57

是的,额外的调用数据字节将被忽略,是的,在长度结束后读取的回调数据是0。

票数 0
EN

Ethereum用户

发布于 2019-01-24 20:49:46

添加smarx的答案(忽略额外的调用数据):

此外:如果动态数组“偏移”点位于给定参数之外(或大小大于实际提供值的数量),会发生什么情况。你能想象所有未定义的东西都是0,还是会抛出一个异常?

对于字节/字符串/数组等动态大小对象,如果大小大于调用数据中提供的值的数量,则将得到一个还原。

您可以使用以下代码在Remix中自己测试这一点:

代码语言:javascript
复制
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);
    }

}
票数 1
EN

Ethereum用户

发布于 2019-01-26 14:25:03

我深入研究了EVM字节码,发现它显式地检查CALLDATASIZE。另外,非付费函数获得自动编译的if (msg.value != 0)恢复。因此,要回答我自己的问题--如果您只是读取任何(未初始化的)内存,您将得到0,但是对于生成的函数Solidity编译器,似乎会自动添加在LT (低于)情况下进行还原的检查(如果有太多的数据,什么都不会发生)。因此,稳健性本身就可以确保参数的某些条件不变,因此没有其他的魔力。

票数 0
EN
页面原文内容由Ethereum提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://ethereum.stackexchange.com/questions/66070

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档