如何在 Solidity 中将地址列表或其他函数作为字节传递?
How to pass list of addresses or another function as bytes in 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)
有办法吗?
来自另一个合约的链上调用
您可以使用 abi.encode
和 abi.encodePacked
将数据 encode 添加到 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
保留每个参数的 leading/trailing(取决于数据类型)零,而 abi.encodePacked
修剪它们。
因此 encodePacked
和 encode
在 passFunctionCall
示例中的组合 returns
0x
58de5f3c // function signature
000000000000000000000000000000000000000000000000000000000000007b // 1st argument
0000000000000000000000000000000000000000000000000000000000000045 // 2nd argument
如果你只 encode
d 所有参数,它会为 bytes4
类型留下尾随零,在这种情况下你不希望这样,因为收件人会读 (hex) "64 zeros" 而不是 (hex)"7b" 作为第一个参数,另一个参数也不正确,并且 (hex)"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']);
returns
0x
0000000000000000000000000000000000000000000000000000000000000033
0000000000000000000000000000000000000000000000000000000000000044
或者您可以使用 encodeFunctionCall() 为函数调用获取 bytes
。
const data = web3.eth.abi.encodeFunctionCall({
name: 'anotherfunction',
type: 'function',
inputs: [{
type: 'uint256',
name: ''
},{
type: 'address',
name: ''
}]
}, ['123', '0x0000000000000000000000000000000000000045']);
returns
0x
58de5f3c // function signature
000000000000000000000000000000000000000000000000000000000000007b // 1st argument
0000000000000000000000000000000000000000000000000000000000000045 // 2nd argument
在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)
有办法吗?
来自另一个合约的链上调用
您可以使用 abi.encode
和 abi.encodePacked
将数据 encode 添加到 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
保留每个参数的 leading/trailing(取决于数据类型)零,而 abi.encodePacked
修剪它们。
因此 encodePacked
和 encode
在 passFunctionCall
示例中的组合 returns
0x
58de5f3c // function signature
000000000000000000000000000000000000000000000000000000000000007b // 1st argument
0000000000000000000000000000000000000000000000000000000000000045 // 2nd argument
如果你只 encode
d 所有参数,它会为 bytes4
类型留下尾随零,在这种情况下你不希望这样,因为收件人会读 (hex) "64 zeros" 而不是 (hex)"7b" 作为第一个参数,另一个参数也不正确,并且 (hex)"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']);
returns
0x
0000000000000000000000000000000000000000000000000000000000000033
0000000000000000000000000000000000000000000000000000000000000044
或者您可以使用 encodeFunctionCall() 为函数调用获取 bytes
。
const data = web3.eth.abi.encodeFunctionCall({
name: 'anotherfunction',
type: 'function',
inputs: [{
type: 'uint256',
name: ''
},{
type: 'address',
name: ''
}]
}, ['123', '0x0000000000000000000000000000000000000045']);
returns
0x
58de5f3c // function signature
000000000000000000000000000000000000000000000000000000000000007b // 1st argument
0000000000000000000000000000000000000000000000000000000000000045 // 2nd argument