You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a Safe transaction batches calls through MultiSend, the signer-facing
output shows only the outer multiSend(bytes) calldata blob. The inner calls
(each call's to, value, operation, and calldata) are exactly what the
signer needs to review, and today they have to decode the packed bytes by hand
or trust the proposer.
The packed format is simple and stable across MultiSend versions. Per call:
uint8 operation || address to (20 bytes) || uint256 value || uint256 dataLength || bytes data
concatenated with no separators inside the single bytes argument of multiSend(bytes) (selector 0x8d80ff0a).
Proposal:
when safe-hash sees --operation 1 with a known MultiSend target (feat: signer-safety warnings for safe-hash (assumed --safe-version, DELEGATECALL) #10 adds
the address table), or translate / calldata-decode sees multiSend(bytes)
calldata, enumerate the inner calls: index, operation, to, value, dataLength,
and the data hex (further translated through the ERC-7730 registry when a
descriptor matches, which fits clearsig's core mission)
flag any inner operation=1 (a delegatecall hidden inside a batch, which
MultiSendCallOnly forbids but plain MultiSend allows)
Edge cases worth tests: empty batch, single call, calls with empty data, a
nested multiSend inside a batch, dataLength pointing past the end of the
blob, and non-canonical junk after the last call.
Reference decoders I used while validating clearsig 0.3.1 against live Safe
vectors, in case they help as prior art:
a ~30-line Python decoder of the packed format (happy to inline it here or
send it as a follow-up PR if you want this feature)
a Solidity test-side decoder doing the same enumeration for Foundry tests
Both agree with on-chain getTransactionHash ground truth on Sepolia and Fuji
for 2-call batches through MultiSendCallOnly 1.4.1.
When a Safe transaction batches calls through MultiSend, the signer-facing
output shows only the outer
multiSend(bytes)calldata blob. The inner calls(each call's
to,value,operation, and calldata) are exactly what thesigner needs to review, and today they have to decode the packed bytes by hand
or trust the proposer.
The packed format is simple and stable across MultiSend versions. Per call:
concatenated with no separators inside the single
bytesargument ofmultiSend(bytes)(selector0x8d80ff0a).Proposal:
safe-hashsees--operation 1with a known MultiSend target (feat: signer-safety warnings for safe-hash (assumed --safe-version, DELEGATECALL) #10 addsthe address table), or
translate/calldata-decodeseesmultiSend(bytes)calldata, enumerate the inner calls: index, operation, to, value, dataLength,
and the data hex (further translated through the ERC-7730 registry when a
descriptor matches, which fits clearsig's core mission)
operation=1(a delegatecall hidden inside a batch, whichMultiSendCallOnly forbids but plain MultiSend allows)
data,dataLengthoverruns,trailing bytes
Edge cases worth tests: empty batch, single call, calls with empty data, a
nested
multiSendinside a batch,dataLengthpointing past the end of theblob, and non-canonical junk after the last call.
Reference decoders I used while validating clearsig 0.3.1 against live Safe
vectors, in case they help as prior art:
send it as a follow-up PR if you want this feature)
Both agree with on-chain
getTransactionHashground truth on Sepolia and Fujifor 2-call batches through MultiSendCallOnly 1.4.1.