diff --git a/src/consolidations/main.eas b/src/consolidations/main.eas index 27e58c3..2e9127a 100644 --- a/src/consolidations/main.eas +++ b/src/consolidations/main.eas @@ -1,7 +1,7 @@ -;; ▗▄▄▄▖▄▄▄▄ ▄▄▄▄ ▄ ▗▞▀▜▌ ▄▄▄ -;; ▐▌ █ █ █ ▝▚▄▟▌▀▄▄ ▄▄▄▄ -;; ▐▌█▀▀▀ ▀▀▀█ █ ▄▄▄▀ █ █ █ -;; ▐▌█▄▄▄ ▄▄▄█ █ █ █ +;; ▗▄▄▄▖▄▄▄▄ ▄▄▄▄ ▄ ▗▞▀▜▌ ▄▄▄ +;; ▐▌ █ █ █ ▝▚▄▟▌▀▄▄ ▄▄▄▄ +;; ▐▌█▀▀▀ ▀▀▀█ █ ▄▄▄▀ █ █ █ +;; ▐▌█▄▄▄ ▄▄▄█ █ █ █ ;; This is an implementation of EIP-7251 style contract handling EL triggerred ;; consolidations. It leverages on the fee mechanism and the queue design of the @@ -50,29 +50,6 @@ ;; -------------------------------------------------------------------------- ;; USER SUBROUTINE ---------------------------------------------------------- ;; -------------------------------------------------------------------------- - ;; - ;; Record new request ~~ - ;; This is the default code path. It will attempt to record a user's request - ;; so long as they pay the required fee. - - ;; If calldatasize == 0, return the current excess requests. - calldatasize ;; [calldatasize] - iszero ;; [calldatasize == 0] - jumpi @read_excess - - ;; Input data has the following layout: - ;; - ;; +--------+--------+ - ;; | source | target | - ;; +--------+--------+ - ;; 48 48 - - ;; Verify the input is exactly INPUT_SIZE bytes. - calldatasize ;; [calldatasize] - push INPUT_SIZE ;; [INPUT_SIZE, calldatasize] - eq ;; [INPUT_SIZE == calldatasize] - iszero ;; [INPUT_SIZE != calldatasize] - jumpi @revert ;; [] ;; Compute the fee using fake expo and the current excess requests. push FEE_UPDATE_FRACTION @@ -88,6 +65,37 @@ push MIN_FEE ;; [min_fee, excess, update_fraction] #include "../common/fake_expo.eas" + ;; If calldatasize matches the expected input size, go to adding the request. + calldatasize ;; [calldatasize, req_fee] + push INPUT_SIZE ;; [INPUT_SIZE, calldatasize, req_fee] + eq ;; [INPUT_SIZE == calldatasize, req_fee] + jumpi @handle_input ;; [req_fee] + + ;; Otherwise calldatasize must be zero. + calldatasize ;; [calldatasize, req_fee] + jumpi @revert ;; [req_fee] + + ;; This is the read path, where we return the current excess. + ;; Reject any callvalue here to prevent lost funds. + callvalue ;; [value, req_fee] + jumpi @revert ;; [req_fee] + + ;; Return req_fee. + push 0 ;; [0, req_fee] + mstore ;; [] + push 32 ;; [32] + push 0 ;; [0, 32] + return ;; [] + +handle_input: + ;; This is the write path. We expect the computed fee on the stack. + ;; Input data has the following layout: + ;; + ;; +--------+--------+ + ;; | source | target | + ;; +--------+--------+ + ;; 48 48 + ;; Determine if the fee provided is enough to cover the request fee. callvalue ;; [callvalue, req_fee] lt ;; [callvalue < req_fee] @@ -167,23 +175,6 @@ stop -read_excess: - ;; This is the read path, where we return the current excess. - ;; Reject any callvalue here to prevent lost funds. - callvalue ;; [value] - iszero ;; [value == 0] - iszero ;; [value != 0] - jumpi @revert - - ;; Load excess requests and return the value. - push SLOT_EXCESS ;; [excess_reqs_slot] - sload ;; [excess_reqs] - push 0 ;; [0, excess_reqs] - mstore ;; [] - push 32 ;; [32] - push 0 ;; [0, 32] - return ;; [] - ;; ---------------------------------------------------------------------------- ;; SYSTEM SUBROUTINE ---------------------------------------------------------- ;; ---------------------------------------------------------------------------- diff --git a/src/withdrawals/main.eas b/src/withdrawals/main.eas index 6099e97..89aa8f2 100644 --- a/src/withdrawals/main.eas +++ b/src/withdrawals/main.eas @@ -55,29 +55,6 @@ ;; -------------------------------------------------------------------------- ;; USER SUBROUTINE ---------------------------------------------------------- ;; -------------------------------------------------------------------------- - ;; - ;; Record new withdrawal request ~~ - ;; This is the default code path. It will attempt to record a user's request - ;; so long as they pay the required fee. - - ;; If calldatasize == 0, return the current excess requests. - calldatasize ;; [calldatasize] - iszero ;; [calldatasize == 0] - jumpi @read_excess - - ;; Input data has the following layout: - ;; - ;; +--------+--------+ - ;; | pubkey | amount | - ;; +--------+--------+ - ;; 48 8 - - ;; Verify the input is exactly 56 bytes. - calldatasize ;; [calldatasize] - push INPUT_SIZE ;; [INPUT_SIZE, calldatasize] - eq ;; [INPUT_SIZE == calldatasize] - iszero ;; [INPUT_SIZE != calldatasize] - jumpi @revert ;; [] ;; Compute the fee using fake expo and the current excess withdrawal requests. push FEE_UPDATE_FRACTION @@ -93,6 +70,37 @@ push MIN_FEE ;; [min_fee, excess, update_fraction] #include "../common/fake_expo.eas" + ;; If calldatasize matches the expected input size, go to adding the request. + calldatasize ;; [calldatasize, req_fee] + push INPUT_SIZE ;; [INPUT_SIZE, calldatasize, req_fee] + eq ;; [INPUT_SIZE == calldatasize, req_fee] + jumpi @handle_input + + ;; Otherwise calldatasize must be zero. + calldatasize ;; [calldatasize, req_fee] + jumpi @revert ;; [req_fee] + + ;; This is the read path, where we return the current fee. + ;; Reject any callvalue here to prevent lost funds. + callvalue ;; [value, req_fee] + jumpi @revert + + ;; Return req_fee. + push 0 ;; [0, req_fee] + mstore ;; [] + push 32 ;; [32] + push 0 ;; [0, 32] + return ;; [] + +handle_input: + ;; This is the write path. We expect the computed fee on the stack. + ;; Input data has the following layout: + ;; + ;; +--------+--------+ + ;; | pubkey | amount | + ;; +--------+--------+ + ;; 48 8 + ;; Determine if the fee provided is enough to cover the withdrawal request fee. callvalue ;; [callvalue, req_fee] lt ;; [callvalue < req_fee] @@ -162,23 +170,6 @@ stop -read_excess: - ;; This is the read path, where we return the current excess. - ;; Reject any callvalue here to prevent lost funds. - callvalue ;; [value] - iszero ;; [value == 0] - iszero ;; [value != 0] - jumpi @revert - - ;; Load excess withdrawal requests and return the value. - push SLOT_EXCESS ;; [excess_reqs_slot] - sload ;; [excess_reqs] - push 0 ;; [0, excess_reqs] - mstore ;; [] - push 32 ;; [32] - push 0 ;; [0, 32] - return ;; [] - ;; ---------------------------------------------------------------------------- ;; SYSTEM SUBROUTINE ---------------------------------------------------------- ;; ---------------------------------------------------------------------------- diff --git a/test/Test.sol b/test/Test.sol index 87a3455..73c3906 100644 --- a/test/Test.sol +++ b/test/Test.sol @@ -50,8 +50,9 @@ abstract contract Test is StdTest { // system contract matches count. function assertExcess(uint256 count) internal { assertStorage(excess_slot, count, "unexpected excess requests"); + uint256 expectedFee = computeFee(count); (, bytes memory data) = addr.call(""); - assertEq(toFixed(data, 0, 32), count, "unexpected excess requests"); + assertEq(uint256(bytes32(data)), expectedFee, "unexpected fee returned"); } }