Open zerosnacks opened 3 weeks ago
Fwiw, the issue is related to how cast abi-encode
works with nested structs that also contain arrays (see my above linked gist). Also, when I try to decode the correct payload it fails:
cast abi-decode -i "UpgradeProposal((address,uint256,bytes)[],address,bytes32)" 0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000defd1edee3e8c5965216bd59c866f7f5307c9b29646563656e7472616c697a6174696f6e206973206e6f74206f7074696f6e616c00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000d7f9f54194c633f36ccd5f3da84ad4a1c38cb2cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000479ba509700000000000000000000000000000000000000000000000000000000000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb521300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000479ba509700000000000000000000000000000000000000000000000000000000000000000000000000000000c2ee6b6af7d616f6e27ce7f4a451aedc2b0f5f5c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000479ba5097000000000000000000000000000000000000000000000000000000000000000000000000000000005d8ba173dc6c3c90c8f7c04c9288bef5fdbad06e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000479ba509700000000000000000000000000000000000000000000000000000000
The syntax is correct for the first block, not the second
The syntax is correct for the first block, not the second
can you elaborate? Not sure I can follow.
In OP "Basic example" is correct, each parameter corresponds to a CLI argument; the "versus (does not work)" block is not correct
In OP "Basic example" is correct, each parameter corresponds to a CLI argument; the "versus (does not work)" block is not correct
correct - as background this example is coming from me since I literally played around with this for an hour yesterday. The syntax ([(1)],123)
would make much more sense as it's a nested struct that I represent here.
Also, more importantly, please check my bash script and the encoding of the complex struct. It's not correct even with the given syntax:
cast abi-encode "UpgradeProposal((address,uint256,bytes)[],address,bytes32)" "[(0xD7f9f54194C633F36CCD5F3da84ad4a1c38cB2cB,0,0x79ba5097),(0xD7f9f54194C633F36CCD5F3da84ad4a1c38cB2cB,0,0x79ba5097)]" "0x8f7a9912416e8AdC4D9c21FAe1415D3318A11897" "0x646563656e7472616c697a6174696f6e206973206e6f74206f7074696f6e616c"
The above command will return a wrong encoding. If you use the correct encoding result from the Solidity script in my test you will see it.
They're 2 different encodings, cast abi-encode encodes for function arguments, not a single struct.
Essentially you're comparing the encoding of (cast abi-encode
):
function f( (address,uint256,bytes)[] arg1, address arg2, bytes32 arg3 )
to (expected):
function g( ((address,uint256,bytes)[],address,bytes32) arg1 )
(which is equivalent to the abi.encode(arg1)
)
You're looking for the second one, so the correct command is achieved by wrapping the struct fields in another pair of parentheses:
cast abi-encode "f(((address,uint256,bytes)[],address,bytes32))" "([(0xD7f9f54194C633F36CCD5F3da84ad4a1c38cB2cB,0,0x79ba5097),(0xD7f9f54194C633F36CCD5F3da84ad4a1c38cB2cB,0,0x79ba5097)],0x8f7a9912416e8AdC4D9c21FAe1415D3318A11897,0x646563656e7472616c697a6174696f6e206973206e6f74206f7074696f6e616c)"
The examples in OP:
$ cast abi-encode "UpgradeProposal((uint256)[],uint256)" "[(1)]" "123"
0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001
$ cast abi-encode "UpgradeProposal(((uint256)[],uint256))" "([(1)],123)"
0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001
Note the extra 0x00..20 at the start
Hmm I see, but:
cast abi-encode "UpgradeProposal(((address,uint256,bytes)[],address,bytes32))" "([(0xD7f9f54194C633F36CCD5F3da84ad4a1c38cB2cB,0,0x79ba5097),(0xD7f9f54194C633F36CCD5F3da84ad4a1c38cB2cB,0,0x79ba5097)],0x8f7a9912416e8AdC4D9c21FAe1415D3318A11897,0x646563656e7472616c697a6174696f6e206973206e6f74206f7074696f6e616c)"
produces the following:
0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000600000000000000000000000008f7a9912416e8adc4d9c21fae1415d3318a11897646563656e7472616c697a6174696f6e206973206e6f74206f7074696f6e616c0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000d7f9f54194c633f36ccd5f3da84ad4a1c38cb2cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000479ba509700000000000000000000000000000000000000000000000000000000000000000000000000000000d7f9f54194c633f36ccd5f3da84ad4a1c38cb2cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000479ba509700000000000000000000000000000000000000000000000000000000
But the correct encoding would be:
0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000defd1edee3e8c5965216bd59c866f7f5307c9b29646563656e7472616c697a6174696f6e206973206e6f74206f7074696f6e616c00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000d7f9f54194c633f36ccd5f3da84ad4a1c38cb2cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000479ba509700000000000000000000000000000000000000000000000000000000000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb521300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000479ba509700000000000000000000000000000000000000000000000000000000000000000000000000000000c2ee6b6af7d616f6e27ce7f4a451aedc2b0f5f5c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000479ba5097000000000000000000000000000000000000000000000000000000000000000000000000000000005d8ba173dc6c3c90c8f7c04c9288bef5fdbad06e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000479ba509700000000000000000000000000000000000000000000000000000000
If you want to replicate, use this:
// SPDX-License-Identifier: WTFPL
pragma solidity ^0.8.19;
contract ProposalId {
struct Call {
address target;
uint256 value;
bytes data;
}
struct UpgradeProposal {
Call[] calls;
address executor;
bytes32 salt;
}
function computeProposalId() external pure returns (bytes memory) {
Call[] memory calls = new Call[](4);
calls[0] = Call({target: 0xD7f9f54194C633F36CCD5F3da84ad4a1c38cB2cB, value: 0, data: hex"79ba5097"});
calls[1] = Call({target: 0x303a465B659cBB0ab36eE643eA362c509EEb5213, value: 0, data: hex"79ba5097"});
calls[2] = Call({target: 0xc2eE6b6af7d616f6e27ce7F4A451Aedc2b0F5f5C, value: 0, data: hex"79ba5097"});
calls[3] = Call({target: 0x5D8ba173Dc6C3c90C8f7C04C9288BeF5FDbAd06E, value: 0, data: hex"79ba5097"});
address executor = 0xdEFd1eDEE3E8c5965216bd59C866f7f5307C9b29;
bytes32 salt = hex"646563656e7472616c697a6174696f6e206973206e6f74206f7074696f6e616c";
UpgradeProposal memory upgradeProposal = UpgradeProposal({calls: calls, executor: executor, salt: salt});
return abi.encode(upgradeProposal);
}
}
the arguments are not the same as in the solidity script: calls
is length 2 in cast and 4 in your "correct encoding"
the arguments are not the same as in the solidity script:
calls
is length 2 in cast and 4 in your "correct encoding"
I'm stupid - wrong executor address in the above example as well. Now everything works well. Can we please have as actionable item that we document how to do such nested structs correctly in the docs?
Thanks @DaniPopes!
Moving this to foundry-rs/book
as the actionable item is related to the documentation and confirmed to not be a bug
Sections
cast abi-encode cast abi-decode
Describe the bug
Document how to correctly pass arguments to
cast abi-encode
when it has multiple parameters in a nested struct with one of them being an array.Context: https://gist.github.com/pcaversaccio/0ef8fb8034594e012a4903dfa992369e
From: https://github.com/foundry-rs/book/issues/1286#issuecomment-2347083110