Skip to content

Commit

Permalink
Merge pull request #33 from fjl/withdrawals-return-fee
Browse files Browse the repository at this point in the history
withdrawals, consolidations: return fee instead of excess requests from read operation
  • Loading branch information
lightclient authored Nov 18, 2024
2 parents b5b9f33 + d4a1e93 commit 3375a2a
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 85 deletions.
79 changes: 35 additions & 44 deletions src/consolidations/main.eas
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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]
Expand Down Expand Up @@ -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 ----------------------------------------------------------
;; ----------------------------------------------------------------------------
Expand Down
71 changes: 31 additions & 40 deletions src/withdrawals/main.eas
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]
Expand Down Expand Up @@ -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 ----------------------------------------------------------
;; ----------------------------------------------------------------------------
Expand Down
3 changes: 2 additions & 1 deletion test/Test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}

Expand Down

0 comments on commit 3375a2a

Please sign in to comment.