update salt

This commit is contained in:
Roman Storm 2020-12-17 15:53:43 -08:00 committed by poma
parent c5e8bd945b
commit a81117a4b9
No known key found for this signature in database
GPG Key ID: BA20CB01FE165657
15 changed files with 115 additions and 381 deletions

View File

@ -1,9 +1,18 @@
DEPLOYER=0xce0042b868300000d44a59004da54a005ffdcf9f
SALT=0x00000000000000000000000000000000000000000000000000000000000325a5
AIRDROP_CHUNK_SIZE=180
# Mainnet
DEPLOYER=0xCEe71753C9820f063b38FDbE4cFDAf1d3D928A80
HASHER=0x83584f83f26aF4eDDA9CBe8C730bc87C364b28fe
VERIFIER=0xce172ce1F20EC0B3728c9965470eaf994A03557A
SALT=0x0000000000000000000000000000000000000000000000000000000047941987
# Goerli
DEPLOYER=0xCEe71753C9820f063b38FDbE4cFDAf1d3D928A80
HASHER=0xf425b830943d086390b1C6CcB34033F2601a5341
VERIFIER=0xe65A2C40f2a8975D4A238a2EaD06137b560aF387
SALT=0x0000000000000000000000000000000000000000000000000000000047941987
# needed only for deploy script
PRIVATE_KEY=
RPC_URL=
NET_ID=
GAS_PRICE_IN_WEI=123000000000
NET_ID=42
GAS_PRICE_IN_WEI=123000000000

21
.gitmodules vendored
View File

@ -1,20 +1,7 @@
[submodule "tornado-anonymity-mining"]
path = tornado-anonymity-mining
url = https://github.com/tornadocash/tornado-anonymity-mining
branch = master
[submodule "tornado-governance"]
path = tornado-governance
url = https://github.com/tornadocash/tornado-governance
branch = master
[submodule "torn-token"]
path = torn-token
url = https://github.com/tornadocash/torn-token
branch = master
[submodule "airdrop"]
path = airdrop
url = https://github.com/tornadocash/airdrop
branch = master
[submodule "tornado-core"]
path = tornado-core
url = https://github.com/tornadocash/tornado-core
branch = create2
[submodule "deployer"]
path = deployer
url = https://github.com/tornadocash/deployer
branch = master

@ -1 +0,0 @@
Subproject commit d3d5a4c0dfe5bb155a3b59864e6055ba96da402f

View File

@ -1,29 +1,13 @@
#!/bin/bash -e
# expecting node v12
cd tornado-core
mkdir -p build
yarn install
yarn build:contract
cd ..
cd deployer
yarn
yarn compile
cd ..
cd torn-token
yarn unlink || true
yarn link
yarn
yarn compile
cd ..
cd tornado-governance
yarn link torn-token
yarn
yarn compile
cd ..
cd tornado-anonymity-mining
yarn link torn-token
yarn
if [[ ! -f "build/circuits/TreeUpdateVerifier.sol" ]]; then
yarn circuit
fi
yarn install
yarn compile
cd ..

@ -1 +1 @@
Subproject commit 4dd141a398978abc6f3d67bad0173652152413fe
Subproject commit c6526c7f020ca2398b6db8a4a75aa793be8c7bb6

17
instances.js Normal file
View File

@ -0,0 +1,17 @@
module.exports = [
{
isETH: false,
tokenAddress: "0xBA62BCfcAaFc6622853cca2BE6Ac7d845BC0f2Dc",
denomination: "1000000000000000000",
domain: "fau-1.tornadocash.eth",
symbol: "FAU",
decimals: 18
},
// {
// isETH: true,
// denomination: "2000000000000000000",
// domain: "eth-2.tornadocash.eth",
// symbol: "ETH",
// decimals: 18
// },
]

View File

@ -4,12 +4,11 @@
"description": "",
"main": "index.js",
"scripts": {
"clean": "rm -rf torn-token/build && rm -rf tornado-anonymity-mining/build/contracts && rm -rf tornado-governance/build",
"clean": "rm -rf torn-token/build && rm -rf tornado-anonymity-mining/build/contracts && rm -rf governance/build",
"generate": "node src/generate.js",
"airdrop": "node src/airdrop.js",
"ens": "node src/ens.js",
"execute": "node src/execute.js",
"build": "./build.sh && yarn airdrop && yarn generate",
"build": "./build.sh && yarn generate",
"deploy": "yarn build && yarn ens && yarn execute",
"eslint": "eslint --ext .js --ignore-path .gitignore src",
"prettier:check": "prettier --check src --config .prettierrc",

View File

@ -1,59 +0,0 @@
require('dotenv').config()
const fs = require('fs')
const ethers = require('ethers')
const { namehash, formatEther } = ethers.utils
const config = require('../torn-token/config')
const { deploy, getContractData } = require('./utils')
const DEPLOYER = process.env.DEPLOYER
const SALT = process.env.SALT
const AIRDROP_CHUNK_SIZE = process.env.AIRDROP_CHUNK_SIZE
const airdrop = getContractData('../torn-token/build/contracts/Airdrop.json')
const actions = []
const list = fs
.readFileSync('./airdrop/airdrop.csv')
.toString()
.split('\n')
.map((a) => a.split(','))
.filter((a) => a.length === 2)
.map((a) => ({ to: a[0], amount: ethers.BigNumber.from(a[1]) }))
const total = list.reduce((acc, a) => acc.add(a.amount), ethers.BigNumber.from(0))
const expectedAirdrop = ethers.BigNumber.from(config.torn.distribution.airdrop.amount)
if (total.gt(expectedAirdrop)) {
console.log(
`Total airdrop amount ${formatEther(total)} is greater than expected ${formatEther(expectedAirdrop)}`,
)
process.exit(1)
}
console.log('Airdrop amount:', formatEther(total))
console.log('Airdrop expected:', formatEther(expectedAirdrop))
let i = 0
while (list.length) {
i++
const chunk = list.splice(0, AIRDROP_CHUNK_SIZE)
const total = chunk.reduce((acc, a) => acc.add(a.amount), ethers.BigNumber.from(0))
actions.push(
deploy({
amount: total.toString(),
contract: airdrop,
args: [namehash(config.voucher.address), chunk],
dependsOn: [config.deployer.address, config.voucher.address],
title: `Airdrop Voucher ${i}`,
description: 'Early adopters voucher coupons',
}),
)
}
// Write output
const result = {
deployer: DEPLOYER,
salt: SALT,
actions,
}
fs.writeFileSync('airdrop.json', JSON.stringify(result, null, ' '))
console.log('Created airdrop.json')

View File

@ -2,8 +2,6 @@ require('dotenv').config()
const ethers = require('ethers')
const actions = require('../actions.json')
const abi = require('../abi/deployer.abi.json')
const erc20 = require('../abi/erc20.abi.json')
const { formatEther } = ethers.utils
const prefix = {
1: '',
@ -18,17 +16,15 @@ async function main() {
const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL)
const wallet = new ethers.Wallet(privateKey, provider)
const deployer = new ethers.Contract(actions.deployer, abi, wallet)
const deployerProxy = new ethers.Contract(actions.actions[0].expectedAddress, abi, wallet)
for (const action of actions.actions.filter((a) => a.contract !== 'Airdrop.sol')) {
for (const action of actions.actions) {
let code = await provider.getCode(action.expectedAddress)
if (code && code !== '0x') {
console.log(`${action.contract} is already deployed`)
console.log(`${action.contract} is already deployed at ${explorer}/address/${action.expectedAddress}`)
continue
}
console.log(`Deploying ${action.contract} to ${action.domain} (${action.expectedAddress})`)
const dep = action === actions.actions[0] ? deployer : deployerProxy
const tx = await dep.deploy(action.bytecode, actions.salt, { gasLimit: 7e6, gasPrice: 20000000000 })
const tx = await deployer.deploy(action.bytecode, actions.salt, { gasLimit: 7e6, gasPrice: 20000000000 })
console.log(`TX hash ${explorer}/tx/${tx.hash}`)
try {
await tx.wait()
@ -43,27 +39,6 @@ async function main() {
// throw new Error(`Failed to deploy ${action.contract}`)
}
}
const voucher = new ethers.Contract(
actions.actions.find((a) => a.contract === 'Voucher.sol').expectedAddress,
erc20,
wallet,
)
for (const action of actions.actions.filter((a) => a.contract === 'Airdrop.sol')) {
let bal = await voucher.balanceOf(action.expectedAddress)
if (bal.eq(0)) {
console.log('This airdrop was already processed, skipping')
continue
}
console.log(`Airdropping ${formatEther(action.amount)} vouchers`)
const tx = await deployerProxy.deploy(action.bytecode, actions.salt, {
gasLimit: 7e6,
gasPrice: 20000000000,
})
console.log(`TX hash ${explorer}/tx/${tx.hash}`)
await tx.wait()
console.log('Airdropped successfully')
}
}
main()

View File

@ -1,236 +1,72 @@
require('dotenv').config()
const fs = require('fs')
const ethers = require('ethers')
const { namehash } = ethers.utils
const config = require('../torn-token/config')
const get = require('get-value')
const { deploy, getContractData, zeroMerkleRoot } = require('./utils')
const { formatUnits } = ethers.utils
const { deploy, getContractData } = require('./utils')
const { DEPLOYER, SALT } = process.env
const { DEPLOYER, SALT, HASHER, VERIFIER } = process.env
const deployer = getContractData('../deployer/build/contracts/Deployer.json')
const torn = getContractData('../torn-token/build/contracts/TORN.json')
const vesting = getContractData('../torn-token/build/contracts/Vesting.json')
const voucher = getContractData('../torn-token/build/contracts/Voucher.json')
const governance = getContractData('../tornado-governance/build/contracts/Governance.json')
const governanceProxy = getContractData('../tornado-governance/build/contracts/LoopbackProxy.json')
const miner = getContractData('../tornado-anonymity-mining/build/contracts/Miner.json')
const rewardSwap = getContractData('../tornado-anonymity-mining/build/contracts/RewardSwap.json')
const tornadoTrees = getContractData('../tornado-anonymity-mining/build/contracts/TornadoTrees.json')
const tornadoProxy = getContractData('../tornado-anonymity-mining/build/contracts/TornadoProxy.json')
const poseidonHasher2 = getContractData('../tornado-anonymity-mining/build/contracts/Hasher2.json')
const poseidonHasher3 = getContractData('../tornado-anonymity-mining/build/contracts/Hasher3.json')
const rewardVerifier = getContractData('../tornado-anonymity-mining/build/contracts/RewardVerifier.json')
const withdrawVerifier = getContractData('../tornado-anonymity-mining/build/contracts/WithdrawVerifier.json')
const treeUpdateVerifier = getContractData(
'../tornado-anonymity-mining/build/contracts/TreeUpdateVerifier.json',
)
const airdrop = require('../airdrop.json')
const instances = require('../instances')
// const deployer = getContractData('../deployer/build/contracts/Deployer.json')
// const verifier = getContractData('../tornado-core/build/contracts/Verifier.json')
// const hasher = getContractData('../tornado-core/build/contracts/Hasher.json')
const ethTornado = getContractData('../tornado-core/build/contracts/ETHTornado.json')
const ercTornado = getContractData('../tornado-core/build/contracts/ERC20Tornado.json')
const actions = []
actions.push(
deploy({
domain: config.deployer.address,
contract: deployer,
args: ['0x0000000000000000000000000000000000000000'],
dependsOn: [],
title: 'Deployment proxy',
description:
'This a required contract to initialize all other contracts. It is simple wrapper around EIP-2470 Singleton Factory that emits an event of contract deployment. The wrapper also validates if the deployment was successful.',
}),
)
// actions.push(
// deploy({
// domain: config.deployer.address,
// contract: deployer,
// args: ['0x0000000000000000000000000000000000000000'],
// dependsOn: [],
// title: 'Deployment proxy',
// description:
// 'This a required contract to initialize all other contracts. It is simple wrapper around EIP-2470 Singleton Factory that emits an event of contract deployment. The wrapper also validates if the deployment was successful.',
// }),
// )
//
// // Deploy Hasher
// actions.push(
// deploy({
// domain: 'hasher.contract.tornadocash.eth',
// contract: hasher,
// title: 'Hasher',
// description: 'MiMC hasher contract',
// dependsOn: [
//
// ]
// }),
// )
//
// // Deploy verifier
// actions.push(
// deploy({
// domain: 'verifier.contract.tornadocash.eth',
// contract: verifier,
// title: 'Verifier',
// description: 'zkSNARK verifier contract for withdrawals',
// }),
// )
// Deploy TORN
const distribution = Object.values(config.torn.distribution).map(({ to, amount }) => ({
to: namehash(get(config, to).address),
amount,
}))
console.log(distribution)
actions.push(
deploy({
domain: config.torn.address,
contract: torn,
args: [namehash(config.governance.address), config.torn.pausePeriod, distribution],
title: 'TORN token',
description: 'Tornado.cash governance token',
}),
)
// Deploy Governance implementation
actions.push(
deploy({
domain: config.governanceImpl.address,
contract: governance,
title: 'Governance implementation',
description: 'Initial implementation of upgradable governance contract',
}),
)
// Deploy Governance proxy
const governanceContract = new ethers.utils.Interface(governance.abi)
const initData = governanceContract.encodeFunctionData('initialize', [namehash(config.torn.address)])
actions.push(
deploy({
domain: config.governance.address,
contract: governanceProxy,
args: [namehash(config.governanceImpl.address), initData],
dependsOn: [config.deployer.address, config.governanceImpl.address],
title: 'Governance Upgradable Proxy',
description:
'EIP-1167 Upgradable Proxy for Governance. It can only be upgraded through a proposal by TORN holders',
}),
)
// Deploy Verifiers
actions.push(
deploy({
domain: config.rewardVerifier.address,
contract: rewardVerifier,
title: 'Reward Verifier',
description: 'ZkSnark verifier smart contract for mining rewards',
}),
)
actions.push(
deploy({
domain: config.withdrawVerifier.address,
contract: withdrawVerifier,
title: 'Withdraw Verifier',
description: 'ZkSnark verifier smart contract for reward withdrawals',
}),
)
actions.push(
deploy({
domain: config.treeUpdateVerifier.address,
contract: treeUpdateVerifier,
title: 'Tree Update Verifier',
description: 'ZkSnark verifier smart contract for validation for account merkle tree updates',
}),
)
// Deploy RewardSwap
actions.push(
deploy({
domain: config.rewardSwap.address,
contract: rewardSwap,
args: [
namehash(config.torn.address),
namehash(config.miningV2.address),
config.torn.distribution.miningV2.amount,
config.miningV2.initialBalance,
config.rewardSwap.poolWeight,
],
title: 'Reward Swap',
description: 'AMM that allows to swap Anonymity Points to TORN',
}),
)
// Deploy PoseidonHasher2
actions.push(
deploy({
domain: config.poseidonHasher2.address,
contract: poseidonHasher2,
title: 'Poseidon hasher 2',
description: 'Poseidon hash function for 2 arguments',
}),
)
// Deploy PoseidonHasher3
actions.push(
deploy({
domain: config.poseidonHasher3.address,
contract: poseidonHasher3,
title: 'Poseidon hasher 3',
description: 'Poseidon hash function for 3 arguments',
}),
)
// Deploy TornadoProxy
const instances = config.miningV2.rates.map((rate) => namehash(rate.instance))
actions.push(
deploy({
domain: config.tornadoProxy.address,
contract: tornadoProxy,
args: [namehash(config.tornadoTrees.address), namehash(config.governance.address), instances],
title: 'TornadoCash Proxy',
description:
'Proxy contract for tornado.cash deposits and withdrawals that records block numbers for mining',
}),
)
// Deploy TornadoTrees
actions.push(
deploy({
domain: config.tornadoTrees.address,
contract: tornadoTrees,
args: [
namehash(config.tornadoProxy.address),
namehash(config.poseidonHasher2.address),
namehash(config.poseidonHasher3.address),
config.tornadoTrees.levels,
],
title: 'TornadoTrees',
description: 'Merkle tree with information about tornado cash deposits and withdrawals',
}),
)
// Deploy Miner
const rates = config.miningV2.rates.map((rate) => ({
instance: namehash(rate.instance),
value: rate.value,
}))
actions.push(
deploy({
domain: config.miningV2.address,
contract: miner,
args: [
namehash(config.rewardSwap.address),
namehash(config.governance.address),
namehash(config.tornadoTrees.address),
[
namehash(config.rewardVerifier.address),
namehash(config.withdrawVerifier.address),
namehash(config.treeUpdateVerifier.address),
],
zeroMerkleRoot,
rates,
],
title: 'Miner',
description: 'Mining contract for Anonymity Points',
}),
)
// Deploy Voucher
const airdrops = airdrop.actions.map((a) => ({ to: a.expectedAddress, amount: a.amount }))
actions.push(
deploy({
domain: config.voucher.address,
contract: voucher,
args: [
namehash(config.torn.address),
namehash(config.governance.address),
config.voucher.duration * 2592000, // 60 * 60 * 24 * 30
airdrops,
],
title: 'Voucher',
description: 'TornadoCash voucher contract for early adopters',
}),
)
// Deploy Vestings
config.vesting.governance.beneficiary = actions.find(
(a) => a.domain === 'governance.contract.tornadocash.eth',
).expectedAddress
const vestings = Object.values(config.vesting)
for (const [i, vest] of vestings.entries()) {
// Deploy instances
for (const instance of instances) {
const args = [VERIFIER, HASHER, instance.denomination, 20]
if (!instance.isETH) {
args.push(instance.tokenAddress)
}
actions.push(
deploy({
domain: vest.address,
contract: vesting,
args: [namehash(config.torn.address), vest.beneficiary, 0, vest.cliff, vest.duration],
title: `Vesting ${i + 1} / ${vestings.length}`,
description: `Vesting contract for ${vest.address}`,
domain: instance.domain,
contract: instance.isETH ? ethTornado : ercTornado,
args,
title: `New Tornado.cash pool for ${formatUnits(instance.denomination, instance.decimals)} of ${
instance.symbol
}`,
description: `Tornado cash instance for ${formatUnits(instance.denomination, instance.decimals)} of ${
instance.symbol
}${instance.isETH ? '' : ` at address ${instance.tokenAddress}`}`,
}),
)
}
@ -239,7 +75,7 @@ for (const [i, vest] of vestings.entries()) {
const result = {
deployer: DEPLOYER,
salt: SALT,
actions: actions.concat(airdrop.actions),
actions: actions,
}
fs.writeFileSync('actions.json', JSON.stringify(result, null, ' '))
console.log('Created actions.json')

View File

@ -1,25 +1,12 @@
require('dotenv').config()
const config = require('../torn-token/config')
const path = require('path')
const { getCreate2Address } = require('@ethersproject/address')
const { keccak256 } = require('@ethersproject/solidity')
const ethers = require('ethers')
const MerkleTree = require('fixed-merkle-tree')
const { poseidon } = require('circomlib')
const DEPLOYER = process.env.DEPLOYER
const EIP_DEPLOYER = '0xce0042B868300000d44A59004Da54A005ffdcf9f'
const SALT = process.env.SALT
const poseidonHash = (items) => poseidon(items)
const poseidonHash2 = (a, b) => poseidonHash([a, b])
const merkleTree = new MerkleTree(20, [], { hashFunction: poseidonHash2 })
const zeroMerkleRoot =
'0x' +
merkleTree
.root()
.toString(16)
.padStart(32 * 2, '0')
function getContractData(contractPath) {
const json = require(contractPath)
return {
@ -31,7 +18,7 @@ function getContractData(contractPath) {
function getAddress(bytecode) {
const initHash = keccak256(['bytes'], [bytecode])
return getCreate2Address(DEPLOYER, SALT, initHash)
return getCreate2Address(EIP_DEPLOYER, SALT, initHash)
}
function deploy({
@ -41,13 +28,15 @@ function deploy({
args,
title = '',
description = '',
dependsOn = [config.deployer.address],
dependsOn = [], //[config.deployer.address],
}) {
console.log('Generating deploy for', contract.name)
let bytecode = contract.bytecode
let constructorArgs
if (args) {
const c = new ethers.ContractFactory(contract.abi, contract.bytecode)
bytecode = c.getDeployTransaction(...args).data
constructorArgs = c.interface.encodeDeploy(args)
}
return {
domain,
@ -56,6 +45,7 @@ function deploy({
bytecode,
expectedAddress: getAddress(bytecode),
title,
constructorArgs,
description,
dependsOn,
}
@ -64,5 +54,4 @@ function deploy({
module.exports = {
deploy,
getContractData,
zeroMerkleRoot,
}

@ -1 +0,0 @@
Subproject commit e65817d298ff0cba9f534eec751dd59ef6583c96

@ -1 +0,0 @@
Subproject commit 95f6bbfe17498f3a77b157652274b27a5e31fed0

1
tornado-core Submodule

@ -0,0 +1 @@
Subproject commit f5d8f6d9718db7cfe3a1d3cbb038618ce52b31cb

@ -1 +0,0 @@
Subproject commit 8b6474c4375764df0dba77ecab7191cfcd912fba