首页 > 解决方案 > 如何在 Solidity 中将地址列表或其他函数作为字节传递?

问题描述

在 Uniswap 智能合约中有这个方法:

function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data)

我想将其称为传递地址作为数据或其他函数。

function uniswapV2Call('0x233', 1, 0, ['0x33','0x44'])

或者

function uniswapV2Call('0x233', 1, 0, anotherfunction)

有什么办法吗?

标签: solidity

解决方案


来自另一个合约的链上调用

您可以使用abi.encodeabi.encodePacked将数据编码bytes.

pragma solidity ^0.8.0;

contract MyContract {
    function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external {
    }
    
    function passArray() external {
        bytes memory data = abi.encode([
            address(0x33),
            address(0x44)
        ]);
        this.uniswapV2Call(address(0x233), 1, 0, data);
    }
    
    function passFuncionCall() external {
        bytes memory data = abi.encodePacked(
            bytes4(keccak256('anotherfunction(uint256,address)')), // function signature
            abi.encode(
                123, // `anotherfunction()` arguments
                address(0x45)
            )
        );
        this.uniswapV2Call(address(0x233), 1, 0, data);
    }
}

abi.encode保留每个参数的前导/尾随(取决于数据类型)零,同时abi.encodePacked修剪它们。

所以示例中的encodePackedandencode的组合passFunctionCall返回

0x
58de5f3c // function signature
000000000000000000000000000000000000000000000000000000000000007b // 1st argument
0000000000000000000000000000000000000000000000000000000000000045 // 2nd argument

如果您只encoded 所有参数,它将为bytes4类型留下尾随零,在这种情况下您不想要,因为接收者将读取 (hex)"64 zeros" 而不是 (hex)"7b" 作为第一个参数,另一个参数也将不正确,并且(十六进制)“45”将被忽略。

0x
58de5f3c00000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000007b
0000000000000000000000000000000000000000000000000000000000000045

// same data, just differently formatted for readability

0x
58de5f3c // function signature
0000000000000000000000000000000000000000000000000000000000000000 // 1st argument
0000000000000000000000000000000000000000000000000000007b00000000 // 2nd argument
00000000000000000000000000000000000000000000000000000045 // ignored

链下生成bytes论点。

您可以使用web3.eth.abi.encodeParameter()例如对地址数组进行编码

const data = web3.eth.abi.encodeParameter('address[2]', ['0x0000000000000000000000000000000000000033','0x0000000000000000000000000000000000000044']);

返回

0x
0000000000000000000000000000000000000000000000000000000000000033
0000000000000000000000000000000000000000000000000000000000000044

或者您可以使用encodeFunctionCall()来获取bytes函数调用。

const data = web3.eth.abi.encodeFunctionCall({
    name: 'anotherfunction',
    type: 'function',
    inputs: [{
        type: 'uint256',
        name: ''
    },{
        type: 'address',
        name: ''
    }]
}, ['123', '0x0000000000000000000000000000000000000045']);

返回

0x
58de5f3c // function signature
000000000000000000000000000000000000000000000000000000000000007b // 1st argument
0000000000000000000000000000000000000000000000000000000000000045 // 2nd argument

推荐阅读