You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Get the current implementation contract address from the upgrade beacon via STATICCALL
Then, put calldata in memory to supply as argument in DELEGATECALL to implementation
Finally, return or revert based on DELEGATECALL status, supplying return buffer in either case
48 bytes long when using an upgrade beacon with a compact address (starts with 5 zero bytes)
0x59595959365960205959596e<upgrade_beacon_last_15_bytes>5afa1551368280375af43d3d93803e602e57fd5bf3
pc op name [stack] <memory> {return_buffer} *return* ~revert~
-- -- ------------------------ --------------------------------------------------
// put four zeroes + size of calldata + another zero on the stack to use later.
00 59 MSIZE [0]
01 59 MSIZE [0, 0]
02 59 MSIZE [0, 0, 0]
03 59 MSIZE [0, 0, 0, 0]
04 36 CALLDATASIZE [0, 0, 0, 0, cds]
05 59 MSIZE [0, 0, 0, 0, cds, 0]
// put size of implementation address returned from upgrade beacon on the stack.
06 60 PUSH1 0x20 [0, 0, 0, 0, cds, 0, 32]
// put three zeroes on the stack: offset in memory for return data, no input data.
08 59 MSIZE [0, 0, 0, 0, cds, 0, 32, 0]
09 59 MSIZE [0, 0, 0, 0, cds, 0, 32, 0, 0]
10 59 MSIZE [0, 0, 0, 0, cds, 0, 32, 0, 0, 0]
// put the address of the compact upgrade beacon onto the stack.
11 6e PUSH15 <upgrade_beacon> [0, 0, 0, 0, cds, 0, 32, 0, 0, 0, beacon]
// put current available gas onto the stack - upgrade beacon is unable to waste it.
27 5a GAS [0, 0, 0, 0, cds, 0, 32, 0, 0, 0, beacon, gas]
// perform static call to upgrade beacon and put returned implementation in memory.
28 fa STATICCALL [0, 0, 0, 0, cds, 0, 1] <impl>
// flip success status stack item. Note that a call to upgrade beacon above will
// never fail unless gas runs out or the call stack depth is too great, in which
// case the next delegatecall will also fail, so we can infer it will be 1 => 0
29 15 ISZERO [0, 0, 0, 0, cds, 0, 0]
// take the implementation from memory and place it onto the stack.
30 51 MLOAD [0, 0, 0, 0, cds, 0, impl]
// put size of calldata and two zeroes onto the stack.
31 36 CALLDATASIZE [0, 0, 0, 0, cds, 0, impl, cds]
32 82 DUP3 [0, 0, 0, 0, cds, 0, impl, cds, 0]
33 80 DUP1 [0, 0, 0, 0, cds, 0, impl, cds, 0, 0]
// load all calldata (0 to calldatasize) into memory starting at position 0.
34 37 CALLDATACOPY [0, 0, 0, 0, cds, 0, impl] <calldata>
// put current available gas onto the stack - 1/64th reserved to handle return.
35 5a GAS [0, 0, 0, 0, cds, 0, impl, gas] <calldata>
// supply calldata, delegatecall to implementation, and put status on the stack.
36 f4 DELEGATECALL [0, 0, suc] {returndata}
// push and arrange items to the stack for getting data from the return buffer.
37 3d RETURNDATASIZE [0, 0, suc, rds]
38 3d RETURNDATASIZE [0, 0, suc, rds, rds]
39 93 SWAP4 [rds, 0, suc, rds, 0]
40 80 DUP1 [rds, 0, suc, rds, 0, 0]
// copy return buffer to memory so as to support dynamically-sized return data.
41 3e RETURNDATACOPY [rds, 0, suc] <returndata>
// put pc to jump to in the event that delegatecall was successful on the stack.
42 60 PUSH1 0x2e [rds, 0, suc, 46]
// jump to that location if delegatecall was successful, otherwise continue.
44 57 JUMPI [rds, 0]
// delegatecall was unsuccessful: revert and pass along returned revert message.
45 fd REVERT [] ~returndata (revert message)~
// jump here if and only if delegatecall was successful.
46 5b JUMPDEST [rds, 0]
// delegatecall was successful: return and pass along returned data.
47 f3 RETURN [] *returndata*