Reputation: 2811
In Uniswap smart contract there's this method:
function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data)
I'd like to call it an pass addresses as data or another function.
function uniswapV2Call('0x233', 1, 0, ['0x33','0x44'])
or
function uniswapV2Call('0x233', 1, 0, anotherfunction)
Is there anyway to do it?
Upvotes: 2
Views: 2548
Reputation: 43521
On-chain call from another contract
You can use abi.encode
and abi.encodePacked
to encode the data to 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
leaves the leading/trailing (depending on the datatype) zeros of each argument, while abi.encodePacked
trims them.
So the combination of encodePacked
and encode
in the passFunctionCall
example returns
0x
58de5f3c // function signature
000000000000000000000000000000000000000000000000000000000000007b // 1st argument
0000000000000000000000000000000000000000000000000000000000000045 // 2nd argument
If you only encode
d all params, it would leave the trailing zeros for the bytes4
type, which you don't want in this case, because the recipient would read (hex)"64 zeros" instead of (hex)"7b" as the first argument, the other argument would be incorrect as well, and the (hex)"45" would be ignored.
0x
58de5f3c00000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000007b
0000000000000000000000000000000000000000000000000000000000000045
// same data, just differently formatted for readability
0x
58de5f3c // function signature
0000000000000000000000000000000000000000000000000000000000000000 // 1st argument
0000000000000000000000000000000000000000000000000000007b00000000 // 2nd argument
00000000000000000000000000000000000000000000000000000045 // ignored
Off-chain generate the bytes
argument.
You can use web3.eth.abi.encodeParameter() for example to encode the address array
const data = web3.eth.abi.encodeParameter('address[2]', ['0x0000000000000000000000000000000000000033','0x0000000000000000000000000000000000000044']);
returns
0x
0000000000000000000000000000000000000000000000000000000000000033
0000000000000000000000000000000000000000000000000000000000000044
Or you can use the encodeFunctionCall() to get bytes
for the function call.
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
Upvotes: 4