Deterministic Deployment Proxy: Magic wrapped in magic

TL;DR: Ethereum contract deployed with a one-time-use account (so it has a deterministic address) that can be used to deploy arbitrary contracts via CREATE2 (so they end up with deterministic addresses).

This allows anyone to deploy a contract to any EVM chain and be sure that the contract lives at the same address on every chain. Similar to how EIP-1820 was deployed, but without the need to hard-code gas-price and gas-limit.


This is definitely magic magic. Thanks for sharing @MicahZoltu!

1 Like

So many potential cross-chain applications, including ERC-725 identity which now uses proxy contracts.

I updated the code to use Yul, which brought costs down a bit.

Yul source:

object "Proxy" {
	// deployment code
	code {
		let size := datasize("runtime")
		datacopy(0, dataoffset("runtime"), size)
		return(0, size)
	object "runtime" {
		// deployed code
		code {
			calldatacopy(0, 0, calldatasize())
			mstore(0, create2(callvalue(), 0, calldatasize(), 0))
			return(12, 20)

The signed deterministic deployment transaction is now:


The init code for the proxy contract is now:


The deployed proxy’s code is now:


For fun, I was able to gas golf the deployment code to:


and the proxy code to:


However, I decided there was value in having Yul source code available for the deployed contract rather than just raw bytecode, so I decided to eat the extra size and costs (they are marginal).


Another nice thing about the switch to Yul is that deploying contracts is now done by supplying only the deployment bytecode as transaction data and put the proxy as the to. This means you can take a normal deployment transaction and only change the to field on it from null to the proxy address (currently 0xb8744b44784dab81e6ab1e73ea3faa47887157b6) and it will deploy via the proxy.

1 Like

Is this because the “runtime” object from above behaves as a fallback function? Otherwise I don’t see how you could take a deployment tx as it is and not have to compute the function selector.

The proxy isn’t written in Solidity, it is written in Yul, so we don’t have to play by the normal rules. :smile:

It is Solidity that has the concept of “parameters” and “ABI”. Yul being just assembly more or less doesn’t have any higher level primitives like that. Your contract can reference calldata via the opcode, but there is no automatic interpretation of it.

1 Like