mirror of
https://github.com/tornadocash/tornado-deploy.git
synced 2025-01-15 15:41:05 +01:00
246 lines
7.7 KiB
JavaScript
246 lines
7.7 KiB
JavaScript
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 { DEPLOYER, SALT } = 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 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.',
|
|
}),
|
|
)
|
|
|
|
// 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()) {
|
|
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}`,
|
|
}),
|
|
)
|
|
}
|
|
|
|
// Write output
|
|
const result = {
|
|
deployer: DEPLOYER,
|
|
salt: SALT,
|
|
actions: actions.concat(airdrop.actions),
|
|
}
|
|
fs.writeFileSync('actions.json', JSON.stringify(result, null, ' '))
|
|
console.log('Created actions.json')
|