|
1 | 1 | # Deterministic Deployment Proxy |
2 | 2 | This is a proxy contract that can be deployed to any chain at the same address, and can then in turn deploy any contract at a deterministic location using CREATE2. To use, first deploy the contract using the one-time-account transaction specified in `output/deployment.json`, then call the `deploy` method on the contract at the address specified in `output/deployment.json` to deploy your contract. |
3 | 3 |
|
4 | | -## Example Usage |
| 4 | +## Usage |
5 | 5 | ```bash |
6 | | -JSON_RPC="http://localhost:1234" |
7 | | - |
8 | | -# start parity in a local container |
9 | | -PARITY_CONTAINER_ID=$(docker container run --rm -d -p 1234:8545 keydonix/parity-instantseal) |
10 | | -# wait for parity to become responsive |
11 | | -until $(curl --output /dev/null --silent --fail $JSON_RPC -X 'POST' -H 'Content-Type: application/json' --data "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\": \"net_version\", \"params\": []}"); do sleep 1; done |
12 | | - |
13 | | -# extract the variables we need from json output |
14 | | -MY_ADDRESS="0x913dA4198E6bE1D5f5E4a40D0667f70C0B5430Eb" |
15 | | -ONE_TIME_SIGNER_ADDRESS="0x$(cat output/deployment.json | jq --raw-output '.signerAddress')" |
16 | | -GAS_COST="0x$(printf '%x' $(($(cat output/deployment.json | jq --raw-output '.gasPrice') * $(cat output/deployment.json | jq --raw-output '.gasLimit'))))" |
17 | | -TRANSACTION="0x$(cat output/deployment.json | jq --raw-output '.transaction')" |
18 | | -DEPLOYER_ADDRESS="0x$(cat output/deployment.json | jq --raw-output '.address')" |
19 | | - |
20 | | -# send gas money to signer |
21 | | -curl $JSON_RPC -X 'POST' -H 'Content-Type: application/json' --data "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\": \"eth_sendTransaction\", \"params\": [{\"from\":\"$MY_ADDRESS\",\"to\":\"$ONE_TIME_SIGNER_ADDRESS\",\"value\":\"$GAS_COST\"}]}" |
22 | | - |
23 | | -# deploy the deployer contract |
24 | | -curl $JSON_RPC -X 'POST' -H 'Content-Type: application/json' --data "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\": \"eth_sendRawTransaction\", \"params\": [\"$TRANSACTION\"]}" |
| 6 | +npm install |
| 7 | +npm run build |
| 8 | +./scripts/test.sh |
| 9 | +``` |
25 | 10 |
|
26 | | -# deploy our contract |
27 | | -# contract: pragma solidity 0.5.8; contract Apple {function banana() external pure returns (uint8) {return 42;}} |
28 | | -DEPLOY_SIGNATURE="9c4ae2d0" |
29 | | -BYTECODE_OFFSET="0000000000000000000000000000000000000000000000000000000000000040" |
30 | | -SALT="0000000000000000000000000000000000000000000000000000000000000000" |
31 | | -BYTECODE_LENGTH="0000000000000000000000000000000000000000000000000000000000000098" |
32 | | -BYTECODE="6080604052348015600f57600080fd5b50607a8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c3cafc6f14602d575b600080fd5b60336049565b6040805160ff9092168252519081900360200190f35b602a9056fea165627a7a7230582061b42c10c5aed258685366454ca535be5306e982bf70d72569122494bc53deb60029" |
33 | | -PADDING="0000000000000000" |
34 | | -curl $JSON_RPC -X 'POST' -H 'Content-Type: application/json' --data "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\": \"eth_sendTransaction\", \"params\": [{\"from\":\"$MY_ADDRESS\",\"to\":\"$DEPLOYER_ADDRESS\", \"data\":\"0x$DEPLOY_SIGNATURE$BYTECODE_OFFSET$SALT$BYTECODE_LENGTH$BYTECODE$PADDING\"}]}" |
| 11 | +### Details |
| 12 | +See `scripts/test.sh` (commented). Change `JSON_RPC` environment variable to the chain of your choice (requires an unlocked wallet with ETH). Notice that the script works against _any_ chain! If the chain already has the deployer contract deployed to it, then you can just comment out the deployment steps (line 21 and 24) and everything else will still function as normal. If you have already deployed your contract with it, it'll fail because your contract already exists at its address. |
35 | 13 |
|
36 | | -# call our contract (we know the address, no matter what chain we ran this script against!) |
37 | | -MY_CONTRACT_ADDRESS="0x8bb88a8d94804d59f8c2fb06d6605e288382e24f" |
38 | | -MY_CONTRACT_METHOD_SIGNATURE="c3cafc6f" |
39 | | -curl $JSON_RPC -X 'POST' -H 'Content-Type: application/json' --data "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\": \"eth_call\", \"params\": [{\"to\":\"$MY_CONTRACT_ADDRESS\", \"data\":\"0x$MY_CONTRACT_METHOD_SIGNATURE\"}, \"latest\"]}" |
40 | | -# expected result is 0x000000000000000000000000000000000000000000000000000000000000002a (hex encoded 42) |
| 14 | +## Explanation |
| 15 | +This repository contains a simple contract that can deploy other contracts with a deterministic address on any chain using CREATE2. The CREATE2 call will deploy a contract (like CREATE opcode) but instead of the address being `keccak256(rlp([deployer_address, nonce]))` it instead uses the hash of the contract's bytecode and a salt. This means that a given deployer address will deploy the same code to the same address no matter _when_ they issue the deployment. The deployer is deployed with a one-time-use-account, so no matter what chain the deployer is on, its address will always be the same. This means the only variables in determining the address of your contract are its bytecode hash and the provided salt. |
41 | 16 |
|
42 | | -# shutdown Parity |
43 | | -docker container stop $PARITY_CONTAINER_ID |
44 | | -``` |
| 17 | +Between the use of CREATE2 opcode and the one-time-use-account for the deployer, we can ensure that a given contract will exist at the _exact_ same address on every chain, but without having to use the same gas pricing or limits every time. |
0 commit comments