diff --git a/src/consolidations/main.eas b/src/consolidations/main.eas index ab48304..2945e59 100644 --- a/src/consolidations/main.eas +++ b/src/consolidations/main.eas @@ -52,25 +52,8 @@ ;; If calldatasize == 0, return the current excess requests. calldatasize ;; [calldatasize] iszero ;; [calldatasize == 0] - iszero ;; [calldatasize != 0] - jumpi @check_input + jumpi @read_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] - push0 ;; [0, excess_reqs] - mstore ;; [] - push 32 ;; [32] - push 0 ;; [0, 32] - return ;; [] - -check_input: ;; Input data has the following layout: ;; ;; +--------+--------+ @@ -178,6 +161,23 @@ check_input: 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] + push0 ;; [0, excess_reqs] + mstore ;; [] + push 32 ;; [32] + push 0 ;; [0, 32] + return ;; [] + ;; ----------------------------------------------------------------------------- ;; SYSTEM SUBROUTINE ----------------------------------------------------------- ;; ----------------------------------------------------------------------------- @@ -236,77 +236,78 @@ accum_loop: eq ;; [i == count, i, count, head_idx, tail_idx] jumpi @update_head ;; [i, count, head_idx, tail_idx] - ;; Precompute record_offset = i*RECORD_SIZE. - dup1 ;; [i, i, count, head_idx, tail_idx] - push RECORD_SIZE ;; [size, i, i, count, head_idx, tail_idx] - mul ;; [record_offset, i, count, head_idx, tail_idx] - ;; Determine the storage slot of the address for this iteration. This value is ;; also the base for the other storage slots containing the source and the target ;; public keys. The base slot will be (queue_offset + (queue_head + i)*SLOTS_PER_ITEM). - dup4 ;; [head_idx, record_offset, i, ..] - dup3 ;; [i, head_idx, record_offset, i, ..] - add ;; [i+head_idx, record_offset, i, ..] - push SLOTS_PER_ITEM ;; [SLOTS_PER_ITEM, i+head_idx, record_offset, i, ..] - mul ;; [SLOTS_PER_ITEM*(i+head_idx), record_offset, i, ..] - push QUEUE_OFFSET ;; [offset, SLOTS_PER_ITEM*(i+head_idx), record_offset, i, ..] - add ;; [addr_offset, record_offset, i, ..] + dup3 ;; [head_idx, i, ..] + dup2 ;; [i, head_idx, i, ..] + add ;; [i+head_idx, i, ..] + push SLOTS_PER_ITEM ;; [SLOTS_PER_ITEM, i+head_idx, i, ..] + mul ;; [SLOTS_PER_ITEM*(i+head_idx), i, ..] + push QUEUE_OFFSET ;; [offset, SLOTS_PER_ITEM*(i+head_idx), i, ..] + add ;; [addr_offset, i, ..] ;; Read address from slot 0. - dup1 ;; [addr_offset, addr_offset, record_offset, i, ..] - sload ;; [addr, addr_offset, record_offset, i, ..] + dup1 ;; [addr_offset, addr_offset, i, ..] + sload ;; [addr, addr_offset, i, ..] ;; Read source[0:32] from slot 1. - swap1 ;; [addr_offset, addr, record_offset, i, ..] - push 1 ;; [1, addr_offset, addr, record_offset, i, ..] - add ;; [slot1_offset, addr, record_offset, i, ..] - dup1 ;; [slot1_offset, slot1_offset, addr, record_offset, i, ..] - sload ;; [source[0:32], slot1_offset, addr, record_offset, i, ..] + swap1 ;; [addr_offset, addr, i, ..] + push 1 ;; [1, addr_offset, addr, i, ..] + add ;; [slot1_offset, addr, i, ..] + dup1 ;; [slot1_offset, slot1_offset, addr, i, ..] + sload ;; [source[0:32], slot1_offset, addr, i, ..] ;; Read source[32:48] and target[0:16] from slot 2. - swap1 ;; [slot1_offset, source[0:32], addr, record_offset, i, ..] - push 1 ;; [1, slot1_offset, source[0:32], addr, record_offset, i, ..] - add ;; [slot2_offset, source[0:32], addr, record_offset, i, ..] - dup1 ;; [slot2_offset, slot2_offset, source[0:32], addr, record_offset, i, ..] - sload ;; [src[32:48] ++ tgt[0:16], slot2_offset, source[0:32], addr, record_offset, i, ..] + swap1 ;; [slot1_offset, source[0:32], addr, i, ..] + push 1 ;; [1, slot1_offset, source[0:32], addr, i, ..] + add ;; [slot2_offset, source[0:32], addr, i, ..] + dup1 ;; [slot2_offset, slot2_offset, source[0:32], addr, i, ..] + sload ;; [src[32:48] ++ tgt[0:16], slot2_offset, source[0:32], addr, i, ..] ;; Read target[16:48] from slot 3. - swap1 ;; [slot2_offset, src[32:48] ++ tgt[0:16], source[0:32], addr, record_offset, i, ..] - push 1 ;; [1, slot2_offset, src[32:48] ++ tgt[0:16], source[0:32], addr, record_offset, i, ..] - add ;; [slot3_offset, src[32:48] ++ tgt[0:16], source[0:32], addr, record_offset, i, ..] - sload ;; [target[16:32], src[32:48] ++ tgt[0:16], source[0:32], addr, record_offset, i, ..] + swap1 ;; [slot2_offset, src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..] + push 1 ;; [1, slot2_offset, src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..] + add ;; [slot3_offset, src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..] + sload ;; [target[16:32], src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..] ;; Write values to memory flat and contiguously. This require combining the ;; four storage elements ;; (addr, source[0:32], source[32:48] ++ target[0:16], target[16:48]) ;; so there is no padding. + ;; Compute offset = i*RECORD_SIZE. + + dup5 ;; [i, target[16:32], src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..] + push RECORD_SIZE ;; [size, i, target[16:32], src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..] + mul ;; [offset, target[16:32], src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..] + ;; Shift addr bytes. - swap3 ;; [addr, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], record_offset, i, ..] - push 12*8 ;; [96, addr, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], record_offset, i, ..] - shl ;; [addr<<96, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], record_offset, i, ..] + swap4 ;; [addr, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], offset, i, ..] + push 12*8 ;; [96, addr, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], offset, i, ..] + shl ;; [addr<<96, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], offset, i, ..] ;; Store addr at offset = i*RECORD_SIZE. - dup5 ;; [record_offset, addr<<96, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], record_offset, i, ..] - mstore ;; [src[32:48] ++ tgt[0:16], source[0:32], target[16:32], record_offset, i, ..] + dup5 ;; [offset, addr<<96, offset, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], i, ..] + mstore ;; [offset, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], i, ..] ;; Store source[0:32] at offset = i*RECORD_SIZE + 20. - swap1 ;; [source[0:32], src[32:48] ++ tgt[0:16], target[16:32], record_offset, i, ..] - dup4 ;; [record_offset, source[0:32], src[32:48] ++ tgt[0:16], target[16:32], record_offset, i, ..] - push 20 ;; [20, record_offset, source[0:32], src[32:48] ++ tgt[0:16], target[16:32], record_offset, i, ..] - add ;; [record_offset+20, source[0:32], src[32:48] ++ tgt[0:16], target[16:32], record_offset, i, ..] - mstore ;; [src[32:48] ++ tgt[0:16], target[16:32], record_offset, i, ..] + swap2 ;; [source[0:32], src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..] + dup4 ;; [offset, source[0:32], src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..] + push 20 ;; [20, offset, source[0:32], src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..] + add ;; [offset+20, source[0:32], src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..] + mstore ;; [src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..] ;; Store src[32:48] ++ tgt[0:16] at offset = i*RECORD_SIZE + 52. - dup3 ;; [record_offset, src[32:48] ++ tgt[0:16], target[16:32], record_offset, i, ..] - push 52 ;; [52, record_offset, src[32:48] ++ tgt[0:16], target[16:32], record_offset, i, ..] - add ;; [record_offset+52, src[32:48] ++ tgt[0:16], target[16:32], record_offset, i, ..] - mstore ;; [target[16:32], record_offset, i, ..] + dup3 ;; [offset, src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..] + push 52 ;; [52, offset, src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..] + add ;; [offset+52, src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..] + mstore ;; [target[16:32], offset, i, ..] ;; Store target[16:48] at offset = i*RECORD_SIZE + 84. - swap1 ;; [record_offset, target[16:32], i, ..] - push 84 ;; [84, record_offset, target[16:32], i, ..] - add ;; [record_offset+84, target[16:32], i, ..] + swap1 ;; [offset, target[16:32], i, ..] + push 84 ;; [84, offset, target[16:32], i, ..] + add ;; [offset+84, target[16:32], i, ..] mstore ;; [i, ..] ;; Increment i. diff --git a/src/withdrawals/main.eas b/src/withdrawals/main.eas index 6ef53f1..234b49c 100644 --- a/src/withdrawals/main.eas +++ b/src/withdrawals/main.eas @@ -59,28 +59,11 @@ ;; 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 withdrawal requests. + ;; If calldatasize == 0, return the current excess requests. calldatasize ;; [calldatasize] iszero ;; [calldatasize == 0] - iszero ;; [calldatasize != 0] - jumpi @check_input + jumpi @read_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] - push0 ;; [0, excess_reqs] - mstore ;; [] - push 32 ;; [32] - push 0 ;; [0, 32] - return ;; [] - -check_input: ;; Input data has the following layout: ;; ;; +--------+--------+ @@ -119,7 +102,7 @@ check_input: sload ;; [req_count] push1 1 ;; [1, req_count] add ;; [req_count+1] - push SLOT_COUNT + push SLOT_COUNT ;; [slot, req_count+1] sstore ;; [] ;; Now insert request into queue. First, compute the base storage slot @@ -128,7 +111,7 @@ check_input: dup1 ;; [tail_idx, tail_idx] push1 3 ;; [3, tail_idx, tail_idx] mul ;; [3*tail_idx, tail_idx] - push QUEUE_OFFSET + push QUEUE_OFFSET ;; [ost, 3*tail_idx, tail_idx] add ;; [slot, tail_idx] ;; Write address to queue. @@ -178,6 +161,23 @@ check_input: 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] + push0 ;; [0, excess_reqs] + mstore ;; [] + push 32 ;; [32] + push 0 ;; [0, 32] + return ;; [] + ;; ----------------------------------------------------------------------------- ;; SYSTEM SUBROUTINE ----------------------------------------------------------- ;; ----------------------------------------------------------------------------- @@ -236,41 +236,39 @@ accum_loop: eq ;; [i == count, i, count, head_idx, tail_idx] jumpi @update_head ;; [i, count, head_idx, tail_idx] - ;; Precompute record_offset = i*RECORD_SIZE. - dup1 ;; [i, i, count, head_idx, tail_idx] - push RECORD_SIZE ;; [size, i, i, count, head_idx, tail_idx] - mul ;; [record_offset, i, count, head_idx, tail_idx] - ;; Determine the storage slot of the address for this iteration. This value is ;; also the base for the other two storage slots containing the public key and ;; amount. The base slot will be (queue_offset + queue_head*3 + i*3). - dup4 ;; [head_idx, record_offset, i, ..] - dup3 ;; [i, head_idx, record_offset, i, ..] - add ;; [i+head_idx, record_offset, i, ..] - push 3 ;; [3, i+head_idx, record_offset, i, ..] - mul ;; [3*(i+head_idx), record_offset, i, ..] - push QUEUE_OFFSET ;; [offset, 3*(i+head_idx), record_offset, i, ..] - add ;; [addr_offset, record_offset, i, ..] + dup3 ;; [head_idx, i, count, head_idx, ..] + dup2 ;; [i, head_idx, i, ..] + add ;; [i+head_idx, i, ..] + push 3 ;; [3, i+head_idx, i, ..] + mul ;; [3*(i+head_idx), i, ..] + push QUEUE_OFFSET ;; [offset, 3*(i+head_idx), i, ..] + add ;; [addr_offset, i, ..] ;; Read address. - dup1 ;; [addr_offset, addr_offset, record_offset, i, ..] - sload ;; [addr, addr_offset, record_offset, i, ..] + dup1 ;; [addr_offset, addr_offset, i, ..] + sload ;; [addr, addr_offset, i, ..] - ;; Compute pk[0:32] offset and read it. - swap1 ;; [addr_offset, addr, record_offset, i, ..] - push 1 ;; [1, addr_offset, addr, record_offset, i, ..] - add ;; [pk1_offset, addr, record_offset, i, ..] - dup1 ;; [pk1_offset, pk1_offset, addr, record_offset, i, ..] - sload ;; [pk[0:32], pk1_offset, addr, record_offset, i, ..] + ;; Compute pk1 offset and read it. + swap1 ;; [addr_offset, addr, i, ..] + push 1 ;; [1, addr_offset, addr, i, ..] + add ;; [pk1_offset, addr, i, ..] + dup1 ;; [pk1_offset, pk1_offset, addr, i, ..] + sload ;; [pk1, pk1_offset, addr, i, ..] ;; Compute pk2_am offset and read it. - swap1 ;; [pk1_offset, pk[0:32], addr, record_offset, i, ..] - push 1 ;; [1, pk1_offset, pk[0:32], addr, record_offset, i, ..] - add ;; [pk2_am_offset, pk[0:32], addr, record_offset, i, ..] - sload ;; [pk2_am, pk[0:32], addr, record_offset, i, ..] + swap1 ;; [pk1_offset, pk1, addr, i, ..] + push 1 ;; [1, pk1_offset, pk1, addr, i, ..] + add ;; [pk2_am_offset, pk1, addr, i, ..] + sload ;; [pk2_am, pk1, addr, i, ..] + + ;; Reorder values. + swap2 ;; [addr, pk1, pk2_am, i, ..] ;; Write values to memory flat and contiguously. This require combining the - ;; three storage elements (addr, pk[0:32], pk2_am) so there is no padding. + ;; three storage elements (addr, pk1, pk2_am) so there is no padding. ;; ;; Each stack element has the following layout: ;; @@ -278,7 +276,7 @@ accum_loop: ;; 0x00 | 00 00 00 00 00 00 00 00 00 00 00 00 aa aa aa aa ;; 0x10 | aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa ;; - ;; B: pk[0:32] + ;; B: pk[0:32] -> pk1 ;; 0x00 | bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb ;; 0x10 | bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb ;; @@ -291,40 +289,47 @@ accum_loop: ;; ;; (A[12:32] ++ B[0:12], B[12:32] ++ C[0:12], C[12:24]) - ;; Shift addr bytes. - swap2 ;; [addr, pk[0:32], pk2_am, record_offset, i, ..] - push 12*8 ;; [96, addr, pk[0:32], pk2_am, record_offset, i, ..] - shl ;; [addr<<96, pk[0:32], pk2_am, record_offset, i, ..] - - ;; Store addr at offset = i*RECORD_SIZE. - dup4 ;; [record_offset, addr<<96, pk[0:32], pk2_am, record_offset, i, ..] - mstore ;; [pk[0:32], pk2_am, record_offset, i, ..] + ;; Compute offset = i*RECORD_SIZE. + dup4 ;; [i, addr, pk1, pk2_am, i, ..] + push RECORD_SIZE ;; [size, i, addr, pk1, pk2_am, i, ..] + mul ;; [offset, addr, pk1, pk2_am, i, ..] - ;; Store pk[0:32] at offset = i*RECORD_SIZE + 20. - dup3 ;; [record_offset, pk[0:32], pk2_am, record_offset, i, ..] - push 20 ;; [20, record_offset, pk[0:32], pk2_am, record_offset, i, ..] - add ;; [record_offset+20, pk[0:32], pk2_am, record_offset, i, ..] - mstore ;; [pk2_am, record_offset, i, ..] + ;; Shift addr bytes. + swap1 ;; [addr, offset, pk1, pk2_am, i, ..] + push 12*8 ;; [96, addr, offset, pk1, pk2_am, i, ..] + shl ;; [addr<<96, offset, pk1, pk2_am, i, ..] + + ;; Store addr at current offset. + dup2 ;; [offset, addr<<96, offset, pk1, pk2_am, i, ..] + mstore ;; [offset, pk1, pk2_am, i, ..] + push 20 ;; [20, offset, pk1, pk2_am, i, ..] + add ;; [offset, pk1, pk2_am, i, ..] + + ;; Store pk1 at offset = i*RECORD_SIZE + 20. + swap1 ;; [pk1, offset, pk2_am, i, ..] + dup2 ;; [offset, pk1, offset, pk2_am, i, ..] + mstore ;; [offset, pk2_am, i, ..] + push 32 ;; [32, offset, pk2_am, i, ..] + add ;; [offset, pk2_am, i, ..] ;; Extract pk2 from pk2_am. - dup1 ;; [pk2_am, pk2_am, record_offset, i, ..] - push pk2_mask ;; [mask, pk2_am, pk2_am, record_offset, i, ..] - and ;; [pk2, pk2_am, record_offset, i, ..] + dup2 ;; [pk2_am, offset, pk2_am, i, ..] + push pk2_mask ;; [mask, pk2_am, offset, pk2_am, i, ..] + and ;; [pk2, offset, pk2_am, i, ..] ;; Store pk2 at offset = i*RECORD_SIZE + 52. - dup3 ;; [record_offset, pk2, pk2_am, record_offset, i, ..] - push 52 ;; [52, record_offset, pk2, pk2_am, record_offset, i, ..] - add ;; [record_offset+52, pk2, pk2_am, record_offset, i, ..] - mstore ;; [pk2_am, record_offset, i, ..] + dup2 ;; [offset, pk2, offset, pk2_am, i, ..] + mstore ;; [offset, pk2_am, i, ..] + push 16 ;; [16, offset, pk2_am, i, ..] + add ;; [offset, pk2_am, i, ..] ;; Extract am from pk2_am. - push 8*8 ;; [shft, pk2_am, record_offset, i, ..] - shr ;; [am, record_offset, i, ..] + swap1 ;; [pk2_am, offset, i, ..] + push 8*8 ;; [shft, pk2_am, offset, i, ..] + shr ;; [am, offset, i, ..] ;; Store am at offset = i*RECORD_SIZE + 68. - swap1 ;; [record_offset, am, i, ..] - push 68 ;; [68, record_offset, am, i, ..] - add ;; [record_offset+68, am, i, ..] + swap1 ;; [offset, am, i, ..] %mstore_uint64_le() ;; [i, ..] ;; Increment i.