EIP-1167: Minimal Proxy Contract implementation with Huff.
This repo supports dynamic address embedding and gas-efficient bytecode generation for a vanity address (like 0x000000...
).
├── src
│ ├── MinimalProxy.huff // using PUSH1 without the jump label
│ ├── MinimalProxyUsingLabel.huff // using the jump label and PUSH2.
│ └── SimpleStore.huff
└── test
├── MinimalProxy.t.sol
└── SimpleStore.t.sol
Embed the address of the delegate destination as follows:
MinimalProxy.huff
:
#define constant ADDRESS = 0x0102030405060708091011121314151617181920 // dummy address
#define constant JUMPI_DST = 0x2b
...
MinimalProxyUsingLabel.huff
:
#define constant ADDRESS = 0x0102030405060708091011121314151617181920 // dummy address
...
MinimalProxy.t.sol
:
contract MinimalProxyTest is Test {
SimpleStore simpleStore;
SimpleStore minimalProxy;
SimpleStore minimalProxyUsingLabel;
SimpleStore minimalProxyWithVanityAddress;
uint256 constant defaultJumpiDst = 0x2b;
address constant vanityAddress = 0x0000000000060708091011121314151617181920;
function setUp() public {
simpleStore = SimpleStore(HuffDeployer.deploy("SimpleStore"));
// 45 bytes: minimal proxy contract
minimalProxy =
SimpleStore(new HuffConfig().with_addr_constant("ADDRESS", address(simpleStore)).deploy("MinimalProxy"));
// 46 bytes: minimal proxy contract using the jump label
minimalProxyUsingLabel = SimpleStore(
new HuffConfig().with_addr_constant("ADDRESS", address(simpleStore)).deploy("MinimalProxyUsingLabel")
);
// 40 bytes: minimal proxy contract with the vanity address
vm.etch(vanityAddress, address(simpleStore).code);
string memory vanityAddressString = Strings.toHexString(uint160(vanityAddress));
uint256 numberOfLeadingZeroBytes = ((2 + 20 * 2) - bytes(vanityAddressString).length) / 2;
string memory jumpiDst = Strings.toHexString(defaultJumpiDst - numberOfLeadingZeroBytes, 1);
minimalProxyWithVanityAddress = SimpleStore(
new HuffConfig().with_constant("ADDRESS", vanityAddressString).with_constant("JUMPI_DST", jumpiDst).deploy("MinimalProxy")
);
}
...
forge test -vvvvv