动态 calldata 在链上,calldata 合并

huangapple go评论70阅读模式
英文:

Dynamic calldata onchain, calldata merging

问题

我想使用Solidity中的通用调用来追加一些数据。假设我有一个如下所示的函数:

function doWork(uint256 number, string name) {
   //...
}

function someOther(uint256 number, string name, (uint256 votes, bytes[] data)[]) {
   //...
}

我正在使用TypeScript构建calldata,只包括number和name属性,如下所示:

defaultAbiCoder.encode([abi], [value, name]);

现在,在Solidity中,我想要通用地追加数据到每个调用中。我相当确定如果在函数调用中传递了额外的数据,它不会引发异常。

通常,执行如下所示:

function _execute(
    address target,
    uint256 value,
    bytes calldata data
) internal virtual {
    (bool success, ) = target.call{value: value}(data);
    require(success, "TLC: underlying transaction reverted");
}

我正在尝试像这样编码附加数据:

function appendResultsToCalldata(ProposalCore storage proposal) internal virtual returns (bytes[] memory) {
    bytes[] memory combinedData = new bytes[](proposal.calldatas.length);
    for (uint i = 0; i < proposal.calldatas.length; i++) {
        // 计算新组合数据的总长度
        bytes memory votesData = abi.encode(proposal.votes[i]);
        uint totalLength = proposal.calldatas[i].length + votesData.length + proposal.voteChoices[i].data.length;
        // 创建一个包含组合数据的新字节数组
        bytes memory data = new bytes(totalLength);

        // 初始化一个偏移变量以跟踪数组中的位置
        uint offset = 0;
        // 复制calldata到组合数据数组
        for (uint j = 0; j < proposal.calldatas[i].length; j++) {
            data[offset++] = proposal.calldatas[i][j];
        }
        // 将投票值转换为字节并复制到组合数据数组
        for (uint j = 0; j < votesData.length; j++) {
            data[offset++] = votesData[j];
        }
        // 将投票选择数据复制到组合数据数组
        for (uint j = 0; j < proposal.voteChoices[i].data.length; j++) {
            data[offset++] = proposal.voteChoices[i].data[j];
        }
        // 将组合数据添加到combinedData数组
        combinedData[i] = data;
    }

    return combinedData;
}

我认为这不是追加calldata的正确方式。如何通用地追加calldata,以便在每个函数调用中追加(uint256 votes, bytes[] data)[]

英文:

I'd like to append some data using some generic call in solidity. Lets say I have a function that looks like so:

function doWork(uint256 number, string name) {
   //...
}

function someOther (uint256 number, string name, (uint256 votes, bytes[] data)[]) {
   //...
}

I'm building the calldata in typescript with just the number and name properties like so:

defaultAbiCoder.encode([abi], [value, name]);

Now in solidity, I'd like to generically append the data to each call. I'm pretty sure if extra data is passed in the function call it will not throw.

Normally this execute like so:

function _execute(
    address target,
    uint256 value,
    bytes calldata data
) internal virtual {
    (bool success, ) = target.call{value: value}(data);
    require(success, &quot;TLC: underlying transaction reverted&quot;);
}

I'm trying to encode the additional data like so:

function appendResultsToCalldata(ProposalCore storage proposal) internal virtual returns (bytes[] memory) {
    bytes[] memory combinedData = new bytes[](proposal.calldatas.length);
    for (uint i = 0; i &lt; proposal.calldatas.length; i++) {
        // Calculate the total length of the new combined data
        bytes memory votesData = abi.encode(proposal.votes[i]);
        uint totalLength = proposal.calldatas[i].length + votesData.length + proposal.voteChoices[i].data.length;
        // Create a new byte array with the combined data
        bytes memory data = new bytes(totalLength);

        // Initialize an offset variable to keep track of where we are in the array
        uint offset = 0;
        // Copy the calldata into the combined data array
        for (uint j = 0; j &lt; proposal.calldatas[i].length; j++) {
            data[offset++] = proposal.calldatas[i][j];
        }
        // Convert the vote value to bytes and copy it into the combined data array
        for (uint j = 0; j &lt; votesData.length; j++) {
            data[offset++] = votesData[j];
        }
        // Copy the vote choice data into the combined data array
        for (uint j = 0; j &lt; proposal.voteChoices[i].data.length; j++) {
            data[offset++] = proposal.voteChoices[i].data[j];
        }
        // Add the combined data to the combinedData array
        combinedData[i] = data;
    }

    return combinedData;
}

I don't think this is the proper way to append the calldata. How can I generically append calldata so that (uint256 votes, bytes[] data)[] is appended to each function call?

答案1

得分: 1

以下是已翻译的内容:

这里展示了一些执行类似操作(向函数调用的数据末尾添加内容)的代码:https://github.com/ConsenSys/gpact/blob/main/contracts/contracts/src/functioncall/interface/AtomicHiddenAuthParameters.sol#L33

这段代码使用abi.encodePacked将各种额外的参数组合成一个字节数组,然后使用bytes.concat将原始数据与额外的参数组合在一起。

有关bytes.concat的详细信息,请参阅:https://docs.soliditylang.org/en/v0.8.17/types.html?highlight=bytes.concat#the-functions-bytes-concat-and-string-concat

英文:

Some code that does similar things (adding stuff to the end of data for a function call) is shown here: https://github.com/ConsenSys/gpact/blob/main/contracts/contracts/src/functioncall/interface/AtomicHiddenAuthParameters.sol#L33

This code uses abi.encodePacked to put the various extra parameters together into a bytes, and then uses bytes.concat to combine the original data with the extra parameters.

For information about bytes.concat see:
https://docs.soliditylang.org/en/v0.8.17/types.html?highlight=bytes.concat#the-functions-bytes-concat-and-string-concat

huangapple
  • 本文由 发表于 2023年1月9日 06:49:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/75051849.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定