-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #61 from pentagonxyz/md/factory
feat: Proxy + Clones
- Loading branch information
Showing
17 changed files
with
1,132 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
/// @title Clones | ||
/// @notice SPDX-License-Identifier: MIT | ||
/// @author Maddiaa <https://github.com/cheethas> | ||
/// @author asnared <https://github.com/abigger87> | ||
/// @notice https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for deploying minimal proxy contracts, also known as "clones". | ||
/// @notice To simply and cheaply clone contract functionality in an immutable way, this standard specifies | ||
/// a minimal bytecode implementation that delegates all calls to a known, fixed address. | ||
/// | ||
/// @notice The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` | ||
/// (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the | ||
/// deterministic method. | ||
/// @notice Adapted from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/Clones.sol) | ||
|
||
#include "./ERC1967Upgrade.huff" | ||
#include "../utils/CommonErrors.huff" | ||
|
||
// BEFORE ADDRESS | ||
//--------------------------------------------------------------------------------// | ||
// Opcode | Opcode + Arguments | Description | Stack View // | ||
//--------------------------------------------------------------------------------// | ||
// 0x3d | 0x36 | RETURNDATASIZE | 0 // | ||
// 0x60 | 0x602d | PUSH1 0x2d | 0x2d 0 // | ||
// 0x80 | 0x36 | DUP1 | 0x2d 0x2d 0 // | ||
// 0x60 | 0x600a | PUSH1 0x0a | 0x0a 0x2d 0x2d 0 // | ||
// 0x3d | 0x3d | RETURNDATASIZE | 0 0x0a 0x2d 0x2d 0 // | ||
// 0x39 | 0x39 | CODECOPY | 0x2d 0 // | ||
// 0x81 | 0x81 | DUP2 | 0 0x2d 0 // | ||
// 0xf3 | 0xf3 | RETURN | 0 // | ||
|
||
// 0x36 | 0x36 | CALLDATASIZE | size // | ||
// 0x3d | 0x3d | RETURNDATASIZE | 0 size // | ||
// 0x3d | 0x3d | RETURNDATASIZE | 0 0 size // | ||
// 0x37 | 0x37 | CALLDATACOPY | // | ||
// 0x3d | 0x3d | RETURNDATASIZE | 0 // | ||
// 0x3d | 0x3d | RETURNDATASIZE | 0 0 // | ||
// 0x3d | 0x3d | RETURNDATASIZE | 0 0 0 // | ||
// 0x36 | 0x36 | CALLDATASIZE | size 0 0 0 // | ||
// 0x3d | 0x3d | RETURNDATASIZE | 0 size 0 0 0 // | ||
// 0x73 | 0x73 | PUSH20 <addr> | addr 0 size 0 0 0 // | ||
|
||
// AFTER ADDRESS | ||
//--------------------------------------------------------------------------------// | ||
// Opcode | Opcode + Arguments | Description | Stack View // | ||
//--------------------------------------------------------------------------------// | ||
// 0x5a | 0x5a | GAS | gas addr 0 size 0 0 0 // | ||
// 0xf4 | 0xf4 | DELEGATECALL | success 0 // | ||
// 0x3d | 0x3d | RETURNDATASIZE | rds success 0 // | ||
// 0x82 | 0x82 | DUP3 | 0 rds success 0 // | ||
// 0x80 | 0x80 | DUP1 | 0 0 rds success 0 // | ||
// 0x3e | 0x3e | RETURNDATACOPY | success 0 // | ||
// 0x90 | 0x90 | SWAP1 | 0 success // | ||
// 0x3d | 0x3d | RETURNDATASIZE | rds 0 success // | ||
// 0x91 | 0x91 | SWAP2 | success rds 0 // | ||
// 0x60 | 0x602b | PUSH1 0x2b | 0x2b success rds 0 // | ||
// 0x57 | 0x57 | JUMPI | Revert if success == 0 // | ||
// 0xfd | 0xfd | REVERT | // | ||
// 0x5b | 0x5b | JUMPDEST | // | ||
// 0xf3 | 0xf3 | RETURN | // | ||
//--------------------------------------------------------------------------------// | ||
|
||
#define constant BYTECODE_BEFORE_ADDRESS = 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000 | ||
#define constant BYTECODE_AFTER_ADDRESS = 0x5af43d82803e903d91602b57fd5bf3 | ||
|
||
/// @notice Clone a contract using `create`. | ||
/// @param {Stack} Implementation - address of the contract to clone. | ||
#define macro CLONE() = takes (1) returns (1) { | ||
CLONE_MACRO(create) | ||
} | ||
|
||
/// @notice Clone a contract to a deterministic address using `create2`. | ||
/// @param {Stack} Implementation - address of the contract to clone. | ||
/// @param {Stack} Salt - The salt to be added to create2. | ||
#define macro CLONE_DETERMINISTIC() = takes (2) returns (1) { | ||
CLONE_MACRO(create2) | ||
} | ||
|
||
/// @dev Can remain inside the scratch space therefore no memory pointer is required | ||
#define macro CLONE_MACRO(deploy_opcode) = takes (2) returns (1) { | ||
// Input Stack: [implementation, salt [optional]] | ||
|
||
// Store the prefix | ||
__RIGHTPAD(0x3d602d80600a3d3981f3363d3d373d3d3d363d73) // [prefix, implementation, salt] | ||
0x00 mstore // [implementation, salt] | ||
|
||
// Place the implementation at memory byte 20 | ||
0x60 shl // [rightpad(implementation), salt] | ||
0x14 mstore // [salt] | ||
|
||
// Add the suffix after the implementation at byte 40 | ||
__RIGHTPAD(0x5af43d82803e903d91602b57fd5bf3) // [suffix, salt] | ||
0x28 mstore // [salt] | ||
|
||
// Create the contract | ||
0x37 // [0x37, salt] | ||
0x00 // [0x00, 0x37, salt] | ||
0x00 // [0x00, 0x00, 0x37, salt] | ||
<deploy_opcode> // [address] * This will be create | create2 | ||
|
||
// Throw exception if deployment fails | ||
dup1 iszero create_failed jumpi // [address] | ||
continue jump | ||
|
||
create_failed: | ||
DEPLOYMENT_FAILED(0x00) | ||
|
||
continue: | ||
} | ||
|
||
|
||
/// @dev Memory pointer required as this function nukes memory and this is part of a library | ||
#define macro PREDICT_DETERMINISTIC_ADDRESS(ptr) = takes (3) returns (1) { | ||
// Input Stack: [implementation, salt, deployer] | ||
swap1 swap2 swap1 // [implementation, deployer, salt] | ||
|
||
// Store the creation code prefix at memory byte 0 | ||
__RIGHTPAD(0x3d602d80600a3d3981f3363d3d373d3d3d363d73) // [prefix, implementation, deployer, salt] | ||
<ptr> mstore // [implementation, deployer, salt] | ||
|
||
// Store the implementation address at memory byte 20 | ||
0x60 shl // [rightpad(implementation), deployer, salt] | ||
<ptr> 0x14 add // [ptr + 0x14, implementation, deployer, salt] | ||
mstore // [deployer, salt] | ||
|
||
// Store the creation code suffix at memory byte 40 | ||
__RIGHTPAD(0x5af43d82803e903d91602b57fd5bf3ff) // [bytecode_after, deployer, salt] | ||
<ptr> 0x28 add // [ptr + 0x28, bytecode_after, deployer, salt] | ||
mstore // [deployer, salt] | ||
|
||
// mstore(add(ptr, 0x38), deployer) | ||
0x60 shl // [rightpad(deployer), salt] | ||
<ptr> 0x38 add // [ptr + 0x38, deployer, salt] | ||
mstore // [salt] | ||
|
||
// mstore(add(ptr, 0x58), salt) | ||
<ptr> 0x4c add // [ptr + 0x58, salt] | ||
mstore // [] | ||
|
||
// Hash and then store in memory | ||
0x37 // [0x37] | ||
<ptr> // [ptr, 0x37] | ||
sha3 // [hash] | ||
|
||
<ptr> 0x6c add // [ptr + 0x6c, hash] | ||
mstore // [] | ||
|
||
// Hash the rest of the data | ||
0x55 // [0x55] | ||
<ptr> 0x37 add // [ptr + 0x37, 0x55] | ||
sha3 // [hash] | ||
|
||
// Clean the upper 96 bits (12 bytes) of the hash | ||
// The remaining 160 bits (20 bytes) are the address | ||
0x60 shl 0x60 shr // [clean(hash)] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/// @title ERC1967 Proxy | ||
/// @notice SPDX-License-Identifier: MIT | ||
/// @author asnared <https://github.com/abigger87> | ||
/// @notice An upgradeable proxy that uses the ERC1967 storage layout. | ||
/// @notice Adapted from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/ERC1967/ERC1967Proxy.sol) | ||
|
||
#include "./Proxy.huff" | ||
#include "./ERC1967Upgrade.huff" | ||
|
||
/// @notice An internal constructor that upgrades the proxy to the implementation and calls the implementation | ||
#define macro ERC1967_PROXY_CONSTRUCTOR() = takes (0) returns (0) { | ||
0x00 // [forceCall] | ||
0x24 calldataload // [data, forceCall] | ||
0x04 calldataload // [address, data, forceCall] | ||
UPGRADE_TO_AND_CALL() // [] | ||
} | ||
|
||
/// @notice Returns the current implementation address | ||
/// @notice Overrideable | ||
#define macro IMPLEMENTATION() = takes (0) returns (1) { | ||
GET_IMPLEMENTATION() | ||
} |
Oops, something went wrong.