Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
AmazingAng authored Sep 4, 2023
1 parent 249e1ef commit da7683e
Showing 1 changed file with 64 additions and 58 deletions.
122 changes: 64 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
## Minimal Proxy Contract with `PUSH0`

**Minimal Proxy Contract with `PUSH0`, or `Clone0` in short, optimize the previous minimal proxy contract ([eip-3855](https://eips.ethereum.org/EIPS/eip-3855)) by 200 gas at deployment, 5 gas at runtime, while remain the same functionalities.**
**Minimal Proxy Contract with `PUSH0`, or `Clone0` in short, optimize the previous minimal proxy contract ([eip-3855](https://eips.ethereum.org/EIPS/eip-3855)) by 200 gas at deployment, 5 gas at runtime, while remaining the same functionalities.**

## Motivation

This standard trys to mimnimize the Minimal Proxy Contract with the newly added `PUSH0` opcodes. The main motivations are:
This standard tries to optimize the Minimal Proxy Contract with the newly added `PUSH0` opcodes. The main motivations are:

1. Reduce the contract bytecode size by `1` byte by removing a redundant `SWAP` opcode.
2. Reduce the runtime gas by replacing two `DUP` (cost `3` gas each) to two `PUSH0` (cost `2` gas each).
3. Increase the readability of the proxy contract by redesigning it from first principles with `PUSH0`.

## Test Cases

Test cases are performed using Foundry, which include:
Test cases are performed using Foundry, which includes:

- invocation with no arguments.
- invocation with arguments.
Expand Down Expand Up @@ -42,31 +42,31 @@ wherein the bytes at indices 9 - 28 (inclusive) are replaced with the 20 byte ad
The disassembly of the standard proxy contract code:

```shell
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
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
Expand All @@ -83,7 +83,7 @@ where the first 9 bytes are the initcode:
602c8060095f395ff3
```

And the rest are runtime/contract code of the standard proxy. The length of the creation code is `53` bytes.
The rest are runtime/contract code of the standard proxy. The length of the creation code is `53` bytes.

### Deploy with Solidity

Expand Down Expand Up @@ -141,37 +141,41 @@ The contract is built from [first principals](https://blog.openzeppelin.com/deep
To copy the calldata, we need to provide the arguments for the `CALLDATACOPY` opcodes, which are `[0, 0, cds]`, where `cds` represents calldata size.

```shell
pc op opcode stack
---- ------ ------------ --------------
[00] 36 CALLDATASIZE cds
[01] 5f PUSH0 0 cds
[02] 5f PUSH0 0 0 cds
[03] 37 CALLDATACOPY
pc op opcode stack
---- --- ------------ ------------------
[00] 36 CALLDATASIZE cds
[01] 5f PUSH0 0 cds
[02] 5f PUSH0 0 0 cds
[03] 37 CALLDATACOPY
```

### Step 2: Delegatecall

To forward the calldata to the delegate call, we need to prepare arguments for the `DELEGATECALL` opcodes, which are `[gas 0xbebe. 0 cds 0 0]`, where `gas` represents the remaining gas, `0xbebe.` represents the address of the implementation contract, and `suc` represents whether the delegatecall is successful.

```shell
[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
pc op opcode stack
---- --- ------------ ------------------
[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
```

### Step 3: Copy the Returned Data from the `DELEGATECALL`

To copy the returndata, we need to provide the arguments for the `RETURNDATACOPY` opcodes, which are `[0, 0, red]`, where `rds` represents size of returndata from the `DELEGATECALL`.

```shell
[1f] 3d RETURNDATASIZE rds suc
[20] 5f PUSH0 0 rds suc
[21] 5f PUSH0 0 0 rds suc
[22] 3e RETURNDATACOPY suc
pc op opcode stack
---- --- ------------ ------------------
[1f] 3d RETURNDATASIZE rds suc
[20] 5f PUSH0 0 rds suc
[21] 5f PUSH0 0 0 rds suc
[22] 3e RETURNDATACOPY suc
```

### Step 4: Return or Revert
Expand All @@ -181,14 +185,16 @@ Lastly we need to return the data or revert the transaction based on whether the
We also need to prepare the argument `[0, rds]` for `REVERT` and `RETURN` opcodes before the `JUMPI`, otherwise we have to prepare them twice. We cannot avoid the `SWAP` operation, because we can only get `rds` after the `DELEGATECALL`.

```shell
[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
pc op opcode stack
---- --- ------------ ------------------
[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
```

In the end, we arrived at the runtime code for Minimal Proxy Contract with `PUSH0`:
Expand All @@ -197,15 +203,15 @@ In the end, we arrived at the runtime code for Minimal Proxy Contract with `PUSH
365f5f375f5f365f73bebebebebebebebebebebebebebebebebebebebe5af43d5f5f3e5f3d91602a57fd5bf3
```

The length of the runtime code is `44` bytes, which reduced `1` byte from the previous Minimal Proxy Contract. Moreover, it replaced the `RETURNDATASIZE` and `DUP` operations to `PUSH0`, which saves gas and increase the readability of the code. In summary, the Minimal Proxy Contract with `PUSH0` reduce `200` gas at deployment and `5` gas at runtime.
The length of the runtime code is `44` bytes, which reduced `1` byte from the previous Minimal Proxy Contract. Moreover, it replaced the `RETURNDATASIZE` and `DUP` operations with `PUSH0`, saving gas and increasing the code's readability. In summary, the Minimal Proxy Contract with `PUSH0` reduce `200` gas at deployment and `5` gas at runtime.

## Backwards Compatibility

Because the new proxy contract standard uses `PUSH0` opcode, it can only be used after Shanghai Upgrade, otherwise, the contract cannot be deployed.
Because the new proxy contract standard uses the `PUSH0` opcode, it can only be used after the Shanghai Upgrade, otherwise, the contract cannot be deployed.

## Security Considerations

The new proxy contract standard behaves exactly the same as the previous one (eip-3855). Here are the security considerations when using minimal proxy contracts:
The new proxy contract standard is identical to the previous one (eip-3855). Here are the security considerations when using minimal proxy contracts:

Certainly, here's a concise summary of the security considerations for Minimal Proxy Contracts:

Expand All @@ -227,4 +233,4 @@ Certainly, here's a concise summary of the security considerations for Minimal P

3. Martin Abbatemarco, Deep dive into the Minimal Proxy contract, https://blog.openzeppelin.com/deep-dive-into-the-minimal-proxy-contract

4. 0age, The More-Minimal Proxy, https://medium.com/@0age/the-more-minimal-proxy-5756ae08ee48
4. 0age, The More-Minimal Proxy, https://medium.com/@0age/the-more-minimal-proxy-5756ae08ee48

0 comments on commit da7683e

Please # to comment.