Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

withdrawals, consolidations: return fee instead of excess requests from read operation #33

Merged
merged 7 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading