Transaction Unwrapping
In certain scenarios, the raw transaction data might not lend itself to be checked against the configured role permissions directly. An example are batch transactions through the MultiSend contract (opens in a new tab). Instead of scoping the data encoding the full batch of transactions, permissions should be checked individually for each call in the batch.
Transaction unwrapping can be configured as a pre-processing step to be applied for specific target addresses. The unwrapping logic is implemented in adapter contracts.
MultiSendUnwrapper
The MultiSendUnwrapper
adapter contract at the official deployment address 0x93B7fCbc63ED8a3a24B59e1C3e6649D50B7427c0
can be used to support unwrapping of batch transaction through the MultiSend contract (opens in a new tab).
To enable multi-send unwrapping call the setTransactionUnwrapper
function as the owner of the Roles mod:
rolesMod.setTransactionUnwrapper(
address(0x9641d764fc13c8B624c04430C7356C1C7C8102e2)), // offical MultiSendCallOnly deployment on mainnet
bytes4(keccak256('multiSend(bytes)'), // multiSend function selectot
address(0x93B7fCbc63ED8a3a24B59e1C3e6649D50B7427c0) // address of the MultiSendUnwrapper
)
Addresses of the official MultiSend deployments on all chains are listed at https://github.com/safe-global/safe-deployments (opens in a new tab).
Custom unwrappers
Custom transaction unwrapping logic can be implemented as contracts conforming to the ITransactionUnwrapper
interface.
interface ITransactionUnwrapper {
function unwrap(
address to,
uint256 value,
bytes calldata data,
Enum.Operation operation
) external view returns (UnwrappedTransaction[] memory result);
}