Skip to content

Commit 24ac39b

Browse files
author
Micah Zoltu
committed
Switches over to Yul.
This shrinks the runtime costs quite a bit, as well as reducing the deployment costs notably.
1 parent 3c156aa commit 24ac39b

File tree

6 files changed

+54
-48
lines changed

6 files changed

+54
-48
lines changed

.vscode/launch.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"type": "node",
6+
"request": "launch",
7+
"name": "compile",
8+
"cwd": "${workspaceFolder}",
9+
"runtimeArgs": [ "-r", "ts-node/register", ],
10+
"args": [ "${workspaceFolder}/scripts/compile.ts", ],
11+
"env": {
12+
"TS_NODE_PROJECT": "${workspaceFolder}/tsconfig.json",
13+
}
14+
},
15+
]
16+
}

scripts/compile.ts

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { promises as filesystem } from 'fs'
22
import * as path from 'path'
3-
import { AbiFunction, AbiEvent } from 'ethereum'
43
import { CompilerOutput, CompilerInput, compileStandardWrapper, CompilerOutputContract } from 'solc'
54
import { rlpEncode } from '@zoltu/rlp-encoder'
65
import { keccak256 } from 'js-sha3'
@@ -18,34 +17,35 @@ export async function ensureDirectoryExists(absoluteDirectoryPath: string) {
1817

1918
async function doStuff() {
2019
const compilerOutput = await compileContracts()
21-
const contract = compilerOutput.contracts['deterministic-deployment-proxy.sol']['DeterministicDeploymentProxy']
20+
const contract = compilerOutput.contracts['deterministic-deployment-proxy.yul']['Proxy']
2221
await ensureDirectoryExists(path.join(__dirname, '..', '/output/'))
23-
await writeAbiJson(contract.abi)
2422
await writeBytecode(contract.evm.bytecode.object)
2523
await writeFactoryDeployerTransaction(contract)
2624
}
2725

2826
async function compileContracts(): Promise<CompilerOutput> {
29-
const solidityFilePath = path.join(__dirname, '..', 'source', 'deterministic-deployment-proxy.sol')
27+
const solidityFilePath = path.join(__dirname, '..', 'source', 'deterministic-deployment-proxy.yul')
3028
const soliditySourceCode = await filesystem.readFile(solidityFilePath, 'utf8')
3129
const compilerInput: CompilerInput = {
32-
language: "Solidity",
30+
language: "Yul",
3331
settings: {
3432
optimizer: {
3533
enabled: true,
36-
runs: 500
34+
details: {
35+
yul: true,
36+
},
3737
},
3838
outputSelection: {
3939
"*": {
4040
"*": [ "abi", "evm.bytecode.object", "evm.gasEstimates" ]
41-
}
42-
}
41+
},
42+
},
4343
},
4444
sources: {
45-
'deterministic-deployment-proxy.sol': {
46-
content: soliditySourceCode
47-
}
48-
}
45+
'deterministic-deployment-proxy.yul': {
46+
content: soliditySourceCode,
47+
},
48+
},
4949
}
5050
const compilerInputJson = JSON.stringify(compilerInput)
5151
const compilerOutputJson = compileStandardWrapper(compilerInputJson)
@@ -55,6 +55,7 @@ async function compileContracts(): Promise<CompilerOutput> {
5555
let concatenatedErrors = "";
5656

5757
for (let error of errors) {
58+
if (/Yul is still experimental/.test(error.message)) continue
5859
concatenatedErrors += error.formattedMessage + "\n";
5960
}
6061

@@ -66,20 +67,13 @@ async function compileContracts(): Promise<CompilerOutput> {
6667
return compilerOutput
6768
}
6869

69-
async function writeAbiJson(abi: (AbiFunction | AbiEvent)[]) {
70-
const filePath = path.join(__dirname, '../output/abi.json')
71-
const fileContents = JSON.stringify(abi, undefined, '\t')
72-
return await filesystem.writeFile(filePath, fileContents, { encoding: 'utf8', flag: 'w' })
73-
}
74-
7570
async function writeBytecode(bytecode: string) {
7671
const filePath = path.join(__dirname, '..', 'output', `bytecode.txt`)
7772
await filesystem.writeFile(filePath, bytecode, { encoding: 'utf8', flag: 'w' })
7873
}
7974

8075
async function writeFactoryDeployerTransaction(contract: CompilerOutputContract) {
81-
// https://github.com/ethereum/solidity/issues/6724 2x seems to be enough for this case... :this-is-fine:
82-
const deploymentGas = Number.parseInt(contract.evm.gasEstimates!.creation.totalCost) * 2
76+
const deploymentGas = 100000 // actual gas costs last measure: 59159; we don't want to run too close though because gas costs can change in forks and we want our address to be retained
8377
const deploymentBytecode = contract.evm.bytecode.object
8478

8579
const nonce = new Uint8Array(0)

scripts/test.sh

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ set -x
33
JSON_RPC="http://localhost:1234"
44

55
# start geth in a local container
6-
GETH_CONTAINER_ID=$(docker container run --rm -d -p 1234:8545 -e GETH_VERBOSITY=3 keydonix/geth-clique)
6+
docker container run --rm -d --name deployment-proxy-geth -p 1234:8545 -e GETH_VERBOSITY=3 keydonix/geth-clique
77
# wait for geth to become responsive
88
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
99

@@ -22,19 +22,14 @@ curl $JSON_RPC -X 'POST' -H 'Content-Type: application/json' --data "{\"jsonrpc\
2222

2323
# deploy our contract
2424
# contract: pragma solidity 0.5.8; contract Apple {function banana() external pure returns (uint8) {return 42;}}
25-
DEPLOY_SIGNATURE="9c4ae2d0"
26-
BYTECODE_OFFSET="0000000000000000000000000000000000000000000000000000000000000040"
27-
SALT="0000000000000000000000000000000000000000000000000000000000000000"
28-
BYTECODE_LENGTH="0000000000000000000000000000000000000000000000000000000000000098"
29-
BYTECODE="6080604052348015600f57600080fd5b50607a8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c3cafc6f14602d575b600080fd5b60336049565b6040805160ff9092168252519081900360200190f35b602a9056fea165627a7a7230582061b42c10c5aed258685366454ca535be5306e982bf70d72569122494bc53deb60029"
30-
PADDING="0000000000000000"
31-
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\"}]}"
32-
33-
# call our contract (we know the address, no matter what chain we ran this script against!)
34-
MY_CONTRACT_ADDRESS="0x8bb88a8d94804d59f8c2fb06d6605e288382e24f"
25+
BYTECODE="6080604052348015600f57600080fd5b5060848061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c3cafc6f14602d575b600080fd5b6033604f565b604051808260ff1660ff16815260200191505060405180910390f35b6000602a90509056fea165627a7a72305820ab7651cb86b8c1487590004c2444f26ae30077a6b96c6bc62dda37f1328539250029"
26+
MY_CONTRACT_ADDRESS=$(curl $JSON_RPC -X 'POST' -H 'Content-Type: application/json' --silent --data "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\": \"eth_call\", \"params\": [{\"from\":\"$MY_ADDRESS\",\"to\":\"$DEPLOYER_ADDRESS\", \"data\":\"0x$BYTECODE\"}, \"latest\"]}" | jq --raw-output '.result')
27+
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\", \"gas\":\"0xf4240\", \"data\":\"0x$BYTECODE\"}]}"
28+
29+
# call our contract (NOTE: MY_CONTRACT_ADDRESS is the same no matter what chain we deploy to!)
3530
MY_CONTRACT_METHOD_SIGNATURE="c3cafc6f"
3631
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\"]}"
3732
# expected result is 0x000000000000000000000000000000000000000000000000000000000000002a (hex encoded 42)
3833

3934
# shutdown Parity
40-
docker container stop $GETH_CONTAINER_ID
35+
docker container stop deployment-proxy-geth

scripts/typings/solc/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ declare module 'solc' {
1010
content: string;
1111
}
1212
interface CompilerInput {
13-
language: "Solidity" | "serpent" | "lll" | "assembly";
13+
language: "Solidity" | "serpent" | "lll" | "assembly" | "Yul";
1414
settings?: any,
1515
sources: {
1616
[globalName: string]: CompilerInputSourceFile|CompilerInputSourceCode,

source/deterministic-deployment-proxy.sol

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
object "Proxy" {
2+
// deployment code
3+
code {
4+
let size := datasize("runtime")
5+
datacopy(0, dataoffset("runtime"), size)
6+
return(0, size)
7+
}
8+
object "runtime" {
9+
// deployed code
10+
code {
11+
calldatacopy(0, 0, calldatasize())
12+
mstore(0, create2(callvalue(), 0, calldatasize(), 0))
13+
return(12, 20)
14+
}
15+
}
16+
}

0 commit comments

Comments
 (0)