Simple Summary
With the newly introduced PUSH0
opcode (eip-3855) at Shanghai Upgrade, we minimized the previous Minimal Proxy Contract (eip-1167) by 200 gas at deployment and 5 gas at runtime, while remain the same functionalities.
Specification
Standard Proxy Contract
The exact runtime code for the minimal proxy contract with PUSH0
is:
365f5f375f5f365f73bebebebebebebebebebebebebebebebebebebebe5af43d5f5f3e5f3d91602a57fd5bf3
wherein the bytes at indices 9 - 28 (inclusive) are replaced with the 20 byte address of the master implementation contract. The length of the runtime code is 44
bytes.
The disassembly of the new minimal proxy contract code:
| pc | op | opcode | stack |
|------|--------|----------------|--------------------|
| [00] | 36 | CALLDATASIZE | cds |
| [01] | 5f | PUSH0 | 0 cds |
| [02] | 5f | PUSH0 | 0 0 cds |
| [03] | 37 | CALLDATACOPY | |
| [04] | 5f | PUSH0 | 0 |
| [05] | 5f | PUSH0 | 0 0 |
| [06] | 36 | CALLDATASIZE | cds 0 0 |
| [07] | 5f | PUSH0 | 0 cds 0 0 |
| [08] | 73bebe.| PUSH20 0xbebe. | 0xbebe. 0 cds 0 0 |
| [1d] | 5a | GAS | gas 0xbebe. 0 cds 0 0|
| [1e] | f4 | DELEGATECALL | suc |
| [1f] | 3d | RETURNDATASIZE | rds suc |
| [20] | 5f | PUSH0 | 0 rds suc |
| [21] | 5f | PUSH0 | 0 0 rds suc |
| [22] | 3e | RETURNDATACOPY | suc |
| [23] | 5f | PUSH0 | 0 suc |
| [24] | 3d | RETURNDATASIZE | rds 0 suc |
| [25] | 91 | SWAP2 | suc 0 rds |
| [26] | 602a | PUSH1 0x2a | 0x2a suc 0 rds |
| [27] | 57 | JUMPI | 0 rds |
| [29] | fd | REVERT | |
| [2a] | 5b | JUMPDEST | 0 rds |
| [2b] | f3 | RETURN | |
Minimal Creation Code
The minimal creation code of the minimal proxy contract is:
602c8060095f395ff3365f5f375f5f365f73bebebebebebebebebebebebebebebebebebebebe5af43d5f5f3e5f3d91602a57fd5bf3
where the first 9 bytes are the initcode:
602c8060095f395ff3
And the rest are runtime/contract code of the proxy. The length of the creation code is 53
bytes.
Implementation
GitHub repo Clone0: GitHub - AmazingAng/Clone0: Clone0 optimize the previous Minimal Proxy Contract (eip-3855) with `PUSH0` opcodes, saving 200 gas at deployment and 5 gas at runtime.
Backwards Compatibility
Because the new minimal proxy contract uses PUSH0
opcode, it can only be deployed after Shanghai Upgrade. It behaves the same as previous Minimal Proxy Contract.
Test Cases
Test cases are performed using Foundry, which include:
-
invocation with no arguments.
-
invocation with arguments.
-
invocation with fixed length return values
-
invocation with variable length return values
-
invocation with revert
-
deploy with minimal creation code (tested on Goerli testnet, link)
Tests for these cases are included in the GitHub repo Minimal Proxy PUSH0.
Reference
-
Peter Murray (@yarrumretep), Nate Welch (@flygoing), Joe Messerman (@JAMesserman), “ERC-1167: Minimal Proxy Contract,” Ethereum Improvement Proposals, no. 1167, June 2018. [Online serial]. Available: ERC-1167: Minimal Proxy Contract.
-
Alex Beregszaszi (@axic), Hugo De la cruz (@hugo-dc), Paweł Bylica (@chfast), “EIP-3855: PUSH0 instruction,” Ethereum Improvement Proposals, no. 3855, February 2021. [Online serial]. Available: EIP-3855: PUSH0 instruction.
-
Martin Abbatemarco, Deep dive into the Minimal Proxy contract, Deep dive into the Minimal Proxy contract - OpenZeppelin blog
-
0age, The More-Minimal Proxy, The More-Minimal Proxy. If you’ve ever looked into how to… | by 0age | Coinmonks | Medium