diff --git a/contracts/BatchExecutor.sol b/contracts/BatchExecutor.sol index ccba38c..f85d056 100644 --- a/contracts/BatchExecutor.sol +++ b/contracts/BatchExecutor.sol @@ -7,14 +7,19 @@ pragma solidity ^0.8.20; /// /// receive/fallback are required so other delegated EOAs can still accept /// plain ETH value transfers from multiSend (empty calldata must not revert). +/// +/// multiSend is onlySelf: without `msg.sender == address(this)`, any third +/// party could call a delegated EOA and drain its ETH. contract BatchExecutor { receive() external payable {} fallback() external payable {} /// @notice Transfer ETH to multiple recipients. - /// @dev Must be called as the delegated EOA (to == EOA after set-code). + /// @dev Must be called as the delegated EOA (to == EOA after set-code), + /// and only by the EOA itself (msg.sender == address(this)). function multiSend(address[] calldata recipients, uint256[] calldata amounts) external payable { + require(msg.sender == address(this), "only self"); uint256 n = recipients.length; require(n == amounts.length, "len"); for (uint256 i = 0; i < n; ) { diff --git a/src/txn_plan/constructor/eip7702.rs b/src/txn_plan/constructor/eip7702.rs index 3b73fd9..07ceff7 100644 --- a/src/txn_plan/constructor/eip7702.rs +++ b/src/txn_plan/constructor/eip7702.rs @@ -146,31 +146,35 @@ pub const EIP7702_DELEGATE_DEPLOY_GAS_LIMIT: u64 = 500_000; /// Runtime exposes `multiSend(address[],uint256[])` (selector `0xbb4c9f0b`). /// Designed as an EIP-7702 delegation target: after set-code, call the EOA /// with multiSend so value transfers use the EOA balance. +/// `multiSend` requires `msg.sender == address(this)` (onlySelf). pub fn delegate_contract_bytecode() -> Vec { // solc --bin --optimize --optimize-runs 200 contracts/BatchExecutor.sol // Includes receive/fallback so multiSend into already-delegated EOAs succeeds. + // Includes onlySelf guard so third parties cannot drain delegated EOAs. const HEX: &str = concat!( - "608060405234801561000f575f80fd5b506102778061001d5f395ff3fe608060", + "608060405234801561000f575f80fd5b506102b28061001d5f395ff3fe608060", "40526004361061001e575f3560e01c8063bb4c9f0b1461002757005b36610025", - "57005b005b610025610035366004610199565b82818114610070576040516246", + "57005b005b6100256100353660046101d4565b3330146100755760405162461b", + "cd60e51b815260206004820152600960248201526837b7363c9039b2b63360b9", + "1b60448201526064015b60405180910390fd5b828181146100ab576040516246", "1bcd60e51b81526020600482015260036024820152623632b760e91b60448201", - "526064015b60405180910390fd5b5f5b81811015610149575f86868381811061", - "008d5761008d610200565b90506020020160208101906100a29190610214565b", - "6001600160a01b03168585848181106100bd576100bd610200565b9050602002", - "01356040515f6040518083038185875af1925050503d805f8114610101576040", - "519150601f19603f3d011682016040523d82523d5f602084013e610106565b60", - "6091505b50509050806101405760405162461bcd60e51b815260040161006790", - "6020808252600490820152631cd95b9960e21b604082015260600190565b5060", - "0101610072565b505050505050565b5f8083601f840112610161575f80fd5b50", - "813567ffffffffffffffff811115610178575f80fd5b60208301915083602082", - "60051b8501011115610192575f80fd5b9250929050565b5f805f806040858703", - "12156101ac575f80fd5b843567ffffffffffffffff808211156101c3575f80fd", - "5b6101cf88838901610151565b909650945060208701359150808211156101e7", - "575f80fd5b506101f487828801610151565b95989497509550505050565b634e", - "487b7160e01b5f52603260045260245ffd5b5f60208284031215610224575f80", - "fd5b81356001600160a01b038116811461023a575f80fd5b939250505056fea2", - "646970667358221220a2fc7415ad69a852d05958c007f06988587d8766968d3b", - "7a734a15534d07c51064736f6c63430008150033", + "5260640161006c565b5f5b81811015610184575f8686838181106100c8576100", + "c861023b565b90506020020160208101906100dd919061024f565b6001600160", + "a01b03168585848181106100f8576100f861023b565b90506020020135604051", + "5f6040518083038185875af1925050503d805f811461013c576040519150601f", + "19603f3d011682016040523d82523d5f602084013e610141565b606091505b50", + "5090508061017b5760405162461bcd60e51b815260040161006c906020808252", + "600490820152631cd95b9960e21b604082015260600190565b506001016100ad", + "565b505050505050565b5f8083601f84011261019c575f80fd5b50813567ffff", + "ffffffffffff8111156101b3575f80fd5b6020830191508360208260051b8501", + "0111156101cd575f80fd5b9250929050565b5f805f80604085870312156101e7", + "575f80fd5b843567ffffffffffffffff808211156101fe575f80fd5b61020a88", + "83890161018c565b90965094506020870135915080821115610222575f80fd5b", + "5061022f8782880161018c565b95989497509550505050565b634e487b7160e0", + "1b5f52603260045260245ffd5b5f6020828403121561025f575f80fd5b813560", + "01600160a01b0381168114610275575f80fd5b939250505056fea26469706673", + "58221220361e305cccaa6daee31e970d468e4f32aa66c7ac631d269ae432b086", + "4e4be77564736f6c63430008150033", ); hex::decode(HEX).expect("invalid BatchExecutor creation bytecode hex") }