Signed-off-by: T-Hax <>
This commit is contained in:
T-Hax 2023-04-15 17:51:29 +00:00
parent 3863e951d8
commit 77958b3909
6 changed files with 127 additions and 75 deletions

@ -1,3 +1,10 @@
# Deployments
- `MinimalInstanceFactory`: [0x9d00007c0f5037157b5be8bff174b194a99118d0](https://etherscan.io/address/0x9d00007c0f5037157b5be8bff174b194a99118d0)
- `InstanceProposalFactory`: [0x10715a092e160793C278a9830F0f8D4417B94D71](https://etherscan.io/address/0x10715a092e160793C278a9830F0f8D4417B94D71)
- `ERC20TornadoCloneable (impl contract)`: [0xED2c9A637379DBF045982335db34Ea948F5FDB10](https://etherscan.io/address/0xED2c9A637379DBF045982335db34Ea948F5FDB10)
- `ETHTornadoCloneable (impl contract)`: [0xFDE7d58A869B7D4B11cA57A35a10D3D95B1683B2](https://etherscan.io/address/0xFDE7d58A869B7D4B11cA57A35a10D3D95B1683B2)
# Reconstruction of `tornado-instances` # Reconstruction of `tornado-instances`
This is a (NOT-MINIMAL) reconstruction of the Tornado Cash `tornado-instances` repository with additional contract variants added. It is not minimal because some dependencies, because of the Github takedowns (and other stuff), had annoying build issues (at least for me) which made me inline a lot of the contract code. This is a (NOT-MINIMAL) reconstruction of the Tornado Cash `tornado-instances` repository with additional contract variants added. It is not minimal because some dependencies, because of the Github takedowns (and other stuff), had annoying build issues (at least for me) which made me inline a lot of the contract code.

@ -21,4 +21,8 @@ module.exports = {
WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
UniswapV3Factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', UniswapV3Factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984',
TWAPSlotsMin: 80, TWAPSlotsMin: 80,
deployments: {
minimalFactory: '0x9d00007c0f5037157b5be8bff174b194a99118d0',
proposalFactory: '0x10715a092e160793C278a9830F0f8D4417B94D71',
},
} }

@ -27,10 +27,8 @@ const prompter = createInterface({ input: process.stdin, output: process.stdout
function _prompt(prompt, resolve) { function _prompt(prompt, resolve) {
prompter.question(prompt, (answer) => { prompter.question(prompt, (answer) => {
if (answer == 'y') { if (answer == 'y') {
userInput.close()
resolve(true) resolve(true)
} else if (answer == 'n') { } else if (answer == 'n') {
userInput.close()
resolve(false) resolve(false)
} else _prompt('', resolve) } else _prompt('', resolve)
}) })
@ -48,34 +46,42 @@ function happyVerifiedMessage(name, address) {
return `\n${name} @ ${address} successfully verified on Etherscan! 🥳\n` return `\n${name} @ ${address} successfully verified on Etherscan! 🥳\n`
} }
function timeout(seconds) {
return new Promise((resolve) => setTimeout(resolve, seconds * 1000))
}
const promptMessageBase = (middle) => `\n${middle}\n\nAre you sure you would like to continue? 🧐 (y/n): ` const promptMessageBase = (middle) => `\n${middle}\n\nAre you sure you would like to continue? 🧐 (y/n): `
async function main() { async function main() {
const minimalFactoryContractFactory = await ethers.getContractFactory('MinimalInstanceFactory') const minimalFactoryFactory = await ethers.getContractFactory('MinimalInstanceFactory')
const proposalFactoryContractFactory = await ethers.getContractFactory('InstanceProposalFactory') const proposalFactoryFactory = await ethers.getContractFactory('InstanceProposalFactory')
const chainId = (await ethers.provider.getNetwork()).chainId
const signer = await ethers.getSigner()
let minimalFactory, proposalFactory, nativeCloneableImplAddr, erc20CloneableImplAddr let minimalFactory, proposalFactory, nativeCloneableImplAddr, erc20CloneableImplAddr
if (await prompt(promptMessageBase('Continuing to MinimalInstanceFactory deployment.'))) { if (await prompt(promptMessageBase('Continuing to MinimalInstanceFactory deployment.'))) {
minimalFactory = await minimalFactoryContractFactory.deploy( minimalFactory = await minimalFactoryFactory.deploy(
config.verifier, config.verifier,
config.hasher, config.hasher,
config.merkleTreeHeight, config.merkleTreeHeight,
) )
console.log(happyDeployedMessage('MinimalInstanceFactory', chainId, minimalFactory.address))
} else { } else {
return '\nDecided to stop at InstanceProposalFactory deployment.\n' return '\nDecided to stop at MinimalInstanceFactory deployment.\n'
} }
console.log(happyDeployedMessage('MinimalInstanceFactory', minimalFactory.address)) console.log(happyDeployedMessage('MinimalInstanceFactory', chainId, minimalFactory.address))
nativeCloneableImplAddr = await minimalFactory.nativeCurImpl() nativeCloneableImplAddr = await minimalFactory.nativeCurImpl()
erc20CloneableImplAddr = await minimalFactory.ERC20Impl() erc20CloneableImplAddr = await minimalFactory.ERC20Impl()
console.log(happyDeployedMessage('ETHTornadoCloneable', nativeCloneableImplAddr)) console.log(happyDeployedMessage('ETHTornadoCloneable', chainId, nativeCloneableImplAddr))
console.log(happyDeployedMessage('ERC20TornadoCloneable', erc20CloneableImplAddr)) console.log(happyDeployedMessage('ERC20TornadoCloneable', chainId, erc20CloneableImplAddr))
if (await prompt(promptMessageBase('Continuing to InstanceProposalFactory deployment.'))) { if (await prompt(promptMessageBase('Continuing to InstanceProposalFactory deployment.'))) {
proposalFactory = await proposalFactoryContractFactory.deploy( proposalFactory = await proposalFactoryFactory.deploy(
config.governance, config.governance,
minimalFactory.address, minimalFactory.address,
config.instanceRegistry, config.instanceRegistry,
@ -84,7 +90,7 @@ async function main() {
config.TWAPSlotsMin, config.TWAPSlotsMin,
) )
console.log(happyDeployedMessage('InstanceProposalFactory', proposalFactory.address)) console.log(happyDeployedMessage('InstanceProposalFactory', chainId, proposalFactory.address))
} else { } else {
return '\nDecided to stop at InstanceProposalFactory deployment.\n' return '\nDecided to stop at InstanceProposalFactory deployment.\n'
} }
@ -96,6 +102,8 @@ async function main() {
}) })
console.log(happyVerifiedMessage('MinimalInstanceFactory', minimalFactory.address)) console.log(happyVerifiedMessage('MinimalInstanceFactory', minimalFactory.address))
console.log('\nWaiting 5 seconds.\n')
await timeout(5)
await hre.run('verify:verify', { await hre.run('verify:verify', {
address: proposalFactory.address, address: proposalFactory.address,
@ -110,6 +118,8 @@ async function main() {
}) })
console.log(happyVerifiedMessage('InstanceProposalFactory', proposalFactory.address)) console.log(happyVerifiedMessage('InstanceProposalFactory', proposalFactory.address))
console.log('\nWaiting 5 seconds.\n')
await timeout(5)
await hre.run('verify:verify', { await hre.run('verify:verify', {
address: nativeCloneableImplAddr, address: nativeCloneableImplAddr,
@ -117,6 +127,8 @@ async function main() {
}) })
console.log(happyVerifiedMessage('ETHTornadoCloneable', nativeCloneableImplAddr)) console.log(happyVerifiedMessage('ETHTornadoCloneable', nativeCloneableImplAddr))
console.log('\nWaiting 5 seconds.\n')
await timeout(5)
await hre.run('verify:verify', { await hre.run('verify:verify', {
address: erc20CloneableImplAddr, address: erc20CloneableImplAddr,

@ -1,32 +0,0 @@
const { ethers } = require('hardhat')
const config = require('../config')
const { generate } = require('../src/generateAddresses')
async function deploy({ address, bytecode, singletonFactory }) {
const contractCode = await ethers.provider.getCode(address)
if (contractCode !== '0x') {
console.log(`Contract ${address} already deployed. Skipping...`)
return
}
await singletonFactory.deploy(bytecode, config.salt, { gasLimit: config.deployGasLimit })
}
async function main() {
const singletonFactory = await ethers.getContractAt('SingletonFactory', config.singletonFactory)
const contracts = await generate()
await deploy({ ...contracts.factory.implementation, singletonFactory })
console.log(`Instance factory contract have been deployed on ${contracts.factory.implementation.address}`)
await deploy({ ...contracts.factory.proxy, singletonFactory })
console.log(`Instance factory proxy contract have been deployed on ${contracts.factory.proxy.address}`)
await deploy({ ...contracts.proposalCreator.implementation, singletonFactory })
console.log(`Proposal creator have been deployed on ${contracts.proposalCreator.implementation.address}`)
await deploy({ ...contracts.proposalCreator.proxy, singletonFactory })
console.log(`Proposal creator proxy have been deployed on ${contracts.proposalCreator.proxy.address}`)
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error)
process.exit(1)
})

@ -1,32 +0,0 @@
const { ethers } = require('hardhat')
const config = require('../config')
const { generate } = require('../src/generateAddresses')
async function deploy({ address, bytecode, singletonFactory }) {
const contractCode = await ethers.provider.getCode(address)
if (contractCode !== '0x') {
console.log(`Contract ${address} already deployed. Skipping...`)
return
}
await singletonFactory.deploy(bytecode, config.salt, { gasLimit: config.deployGasLimit })
}
async function main() {
const singletonFactory = await ethers.getContractAt('SingletonFactory', config.singletonFactory)
const contracts = await generate()
await deploy({ ...contracts.sidechainFactory.implementation, singletonFactory })
await deploy({ ...contracts.sidechainFactory.proxy, singletonFactory })
console.log(
`SidechainInstanceFactory contract have been deployed on ${contracts.sidechainFactory.implementation.address} address`,
)
console.log(
`SidechainInstanceFactory proxy contract have been deployed on ${contracts.sidechainFactory.proxy.address} address`,
)
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error)
process.exit(1)
})

93
scripts/verify.js Normal file

@ -0,0 +1,93 @@
require('dotenv').config()
const hre = require('hardhat')
const config = require('../config')
const { createInterface } = require('readline')
const prompter = createInterface({ input: process.stdin, output: process.stdout })
function _prompt(promptMessage, predicate, resolve) {
prompter.question(promptMessage, (answer) => {
if (predicate(answer)) {
resolve(answer)
} else {
_prompt('', predicate, resolve)
}
})
}
const addressPromptMessage = (contractName) =>
`\n\nPlease enter the deploy address of the ${contractName} contract (CTRL-D/C to exit): `
function addressPrompt(name) {
return new Promise((resolve) =>
_prompt(addressPromptMessage(name), (answer) => answer.length === 42 || answer === 'skip', resolve),
)
}
function happyVerifiedMessage(name, address) {
return `\n${name} @ ${address} successfully verified on Etherscan! 🥳\n`
}
function timeout(seconds) {
return new Promise((resolve) => setTimeout(resolve, seconds * 1000))
}
async function main() {
let minimalFactoryAddr = await addressPrompt('MinimalInstanceFactory')
let proposalFactoryAddr = await addressPrompt('InstanceProposalFactory')
let nativeCloneableImplAddr = await addressPrompt('ETH Instance Clone')
let erc20CloneableImplAddr = await addressPrompt('Token Instance Clone')
if (minimalFactoryAddr !== 'skip') {
await hre.run('verify:verify', {
address: minimalFactoryAddr,
constructorArguments: [config.verifier, config.hasher, config.merkleTreeHeight],
})
console.log(happyVerifiedMessage('MinimalInstanceFactory', minimalFactoryAddr))
}
console.log('\nWaiting 5 seconds.\n')
await timeout(5)
if (proposalFactoryAddr !== 'skip') {
await hre.run('verify:verify', {
address: proposalFactoryAddr,
constructorArguments: [
config.governance,
minimalFactoryAddr,
config.instanceRegistry,
config.UniswapV3Factory,
config.WETH,
config.TWAPSlotsMin,
],
})
console.log(happyVerifiedMessage('InstanceProposalFactory', proposalFactoryAddr))
}
console.log('\nWaiting 5 seconds.\n')
await timeout(5)
if (nativeCloneableImplAddr !== 'skip') {
await hre.run('verify:verify', {
address: nativeCloneableImplAddr,
constructorArguments: [config.verifier, config.hasher],
})
console.log(happyVerifiedMessage('ETHTornadoCloneable', nativeCloneableImplAddr))
}
console.log('\nWaiting 5 seconds.\n')
await timeout(5)
if (erc20CloneableImplAddr !== 'skip') {
await hre.run('verify:verify', {
address: erc20CloneableImplAddr,
constructorArguments: [config.verifier, config.hasher],
})
console.log(happyVerifiedMessage('ERC20TornadoCloneable', erc20CloneableImplAddr))
}
}
main().then((res) => {
console.log(res ?? '\nScript succesfully finished.\n')
})