diff --git a/.env.example b/.env.example index f8818b5..166127c 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,4 @@ ETHERSCAN_KEY= ALCHEMY_KEY= PRIVATE_KEY= +INFURA_API_KEY= diff --git a/README.md b/README.md index ccfdc1f..de8f727 100644 --- a/README.md +++ b/README.md @@ -41,3 +41,24 @@ yarn test ``` Test scripts cover instance factory deployment, proposal deployment and executing proposal. + +## Deploy + +Check config.js for actual values. + +With `salt` = `0x0000000000000000000000000000000000000000000000000000000047941987` address must be: + +1. `InstanceFactory` - `0x7a6e627DC6F66617b4A74Be097A8f56c622fa24c` + +Check addresses with current config: + +```shell +yarn compile +node -e 'require("./src/generateAddresses").generateWithLog()' +``` + +Deploy InstanceFactory: + +```shell +npx hardhat run scripts/deployInstanceFactory.js --network mainnet +``` diff --git a/config.js b/config.js index 1d11ea8..fa4b8c3 100644 --- a/config.js +++ b/config.js @@ -6,10 +6,12 @@ module.exports = { router: '0xd90e2f925DA726b50C4Ed8D0Fb90Ad053324F31b', merkleTreeHeight: 20, singletonFactory: '0xce0042B868300000d44A59004Da54A005ffdcf9f', + singletonFactoryVerboseWrapper: '0xCEe71753C9820f063b38FDbE4cFDAf1d3D928A80', salt: '0x0000000000000000000000000000000000000000000000000000000047941987', COMP: '0xc00e94Cb662C3520282E6f5717214004A7f26888', TORN: '0x77777FeDdddFfC19Ff86DB637967013e6C6A116C', tornWhale: '0xF977814e90dA44bFA03b6295A0616a897441aceC', compWhale: '0xF977814e90dA44bFA03b6295A0616a897441aceC', creationFee: '200000000000000000000', // 200 TORN + deployGasLimit: 7000000, } diff --git a/contracts/libraries/SingletonFactory.sol b/contracts/libraries/SingletonFactory.sol new file mode 100644 index 0000000..13653e5 --- /dev/null +++ b/contracts/libraries/SingletonFactory.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +/** + *Submitted for verification at Etherscan.io on 2020-03-30 + */ + +pragma solidity 0.6.2; + +/** + * @title Singleton Factory (EIP-2470) + * @notice Exposes CREATE2 (EIP-1014) to deploy bytecode on deterministic addresses based on initialization code and salt. + * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) + */ +contract SingletonFactory { + /** + * @notice Deploys `_initCode` using `_salt` for defining the deterministic address. + * @param _initCode Initialization code. + * @param _salt Arbitrary value to modify resulting address. + * @return createdContract Created contract address. + */ + function deploy(bytes memory _initCode, bytes32 _salt) public returns (address payable createdContract) { + assembly { + createdContract := create2(0, add(_initCode, 0x20), mload(_initCode), _salt) + } + } +} +// IV is a value changed to generate the vanity address. +// IV: 6583047 diff --git a/hardhat.config.js b/hardhat.config.js index 6c85282..cec68c9 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -10,6 +10,15 @@ require('solidity-coverage') module.exports = { solidity: { compilers: [ + { + version: '0.6.2', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, { version: '0.6.12', settings: { @@ -42,10 +51,17 @@ module.exports = { allowUnlimitedContractSize: false, blockGasLimit: 50000000, }, + rinkeby: { + url: `https://rinkeby.infura.io/v3/${process.env.INFURA_API_KEY}`, + accounts: process.env.PRIVATE_KEY + ? [process.env.PRIVATE_KEY] + : { mnemonic: 'test test test test test junk' }, + }, mainnet: { url: `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_KEY}`, - accounts: [process.env.PRIVATE_KEY], - timeout: 2147483647, + accounts: process.env.PRIVATE_KEY + ? [process.env.PRIVATE_KEY] + : { mnemonic: 'test test test test test junk' }, }, }, mocha: { timeout: 9999999999 }, diff --git a/package.json b/package.json index 6d94639..3b3705f 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "tornado-cli": "^0.0.1", "tornado-core": "https://github.com/tornadocash/tornado-core.git", "tornado-governance": "2.0.0", - "tornado-relayer-registry": "https://github.com/tornadocash/tornado-relayer-registry.git" + "tornado-relayer-registry": "https://github.com/Rezan-vm/tornado-relayer-registry.git" }, "devDependencies": { "@nomiclabs/hardhat-ethers": "^2.0.2", diff --git a/scripts/deployInstanceFactory.js b/scripts/deployInstanceFactory.js new file mode 100644 index 0000000..60d639a --- /dev/null +++ b/scripts/deployInstanceFactory.js @@ -0,0 +1,26 @@ +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.factoryContract, singletonFactory }) + console.log(`Instance factory contract have been deployed on ${contracts.factoryContract.address} address`) +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error) + process.exit(1) + }) diff --git a/src/generateAddresses.js b/src/generateAddresses.js new file mode 100644 index 0000000..21ea249 --- /dev/null +++ b/src/generateAddresses.js @@ -0,0 +1,46 @@ +const { ethers } = require('hardhat') +const defaultConfig = require('../config') + +async function generate(config = defaultConfig) { + const FactoryFactory = await ethers.getContractFactory('InstanceFactory') + const deploymentBytecodeFactory = + FactoryFactory.bytecode + + FactoryFactory.interface + .encodeDeploy([ + config.verifier, + config.hasher, + config.merkleTreeHeight, + config.governance, + config.instanceRegistry, + config.TORN, + config.creationFee, + ]) + .slice(2) + + const factoryAddress = ethers.utils.getCreate2Address( + config.singletonFactory, + config.salt, + ethers.utils.keccak256(deploymentBytecodeFactory), + ) + + const result = { + factoryContract: { + address: factoryAddress, + bytecode: deploymentBytecodeFactory, + isProxy: false, + }, + } + + return result +} + +async function generateWithLog() { + const contracts = await generate() + console.log('Instance factory contract: ', contracts.factoryContract.address) + return contracts +} + +module.exports = { + generate, + generateWithLog, +} diff --git a/scripts/permit.js b/src/permit.js similarity index 100% rename from scripts/permit.js rename to src/permit.js diff --git a/test/factory.test.js b/test/factory.test.js index 1f7fa56..fa0b9a7 100644 --- a/test/factory.test.js +++ b/test/factory.test.js @@ -5,7 +5,8 @@ const { expect } = require('chai') const { BigNumber } = require('@ethersproject/bignumber') const config = require('../config') const { getSignerFromAddress, minewait } = require('./utils') -const { PermitSigner } = require('../scripts/permit.js') +const { PermitSigner } = require('../src/permit.js') +const { generate } = require('../src/generateAddresses') describe('Instance Factory Tests', () => { const ProposalState = { @@ -42,18 +43,18 @@ describe('Instance Factory Tests', () => { config.instanceRegistry, ) - // deploy instance factory - const InstanceFactory = await ethers.getContractFactory('InstanceFactory') - const instanceFactory = await InstanceFactory.connect(deployer).deploy( - config.verifier, - config.hasher, - config.merkleTreeHeight, - config.governance, - config.instanceRegistry, - config.TORN, - config.creationFee, + // deploy InstanceFactory with CREATE2 + const singletonFactory = await ethers.getContractAt( + 'SingletonFactory', + config.singletonFactoryVerboseWrapper, ) - await instanceFactory.deployed() + const contracts = await generate() + if ((await ethers.provider.getCode(contracts.factoryContract.address)) == '0x') { + await singletonFactory.deploy(contracts.factoryContract.bytecode, config.salt, { + gasLimit: config.deployGasLimit, + }) + } + const instanceFactory = await ethers.getContractAt('InstanceFactory', contracts.factoryContract.address) return { sender, diff --git a/test/instance.tests.js b/test/instance.tests.js index 6b61805..a85af3b 100644 --- a/test/instance.tests.js +++ b/test/instance.tests.js @@ -6,6 +6,7 @@ const { BigNumber } = require('@ethersproject/bignumber') const { rbigint, createDeposit, toHex, generateProof, initialize } = require('tornado-cli') const config = require('../config') const { getSignerFromAddress, minewait } = require('./utils') +const { generate } = require('../src/generateAddresses') describe('Instance Factory Tests', () => { const ProposalState = { @@ -46,18 +47,18 @@ describe('Instance Factory Tests', () => { config.router, ) - // deploy instance factory - const InstanceFactory = await ethers.getContractFactory('InstanceFactory') - const instanceFactory = await InstanceFactory.connect(deployer).deploy( - config.verifier, - config.hasher, - config.merkleTreeHeight, - config.governance, - config.instanceRegistry, - config.TORN, - config.creationFee, + // deploy InstanceFactory with CREATE2 + const singletonFactory = await ethers.getContractAt( + 'SingletonFactory', + config.singletonFactoryVerboseWrapper, ) - await instanceFactory.deployed() + const contracts = await generate() + if ((await ethers.provider.getCode(contracts.factoryContract.address)) == '0x') { + await singletonFactory.deploy(contracts.factoryContract.bytecode, config.salt, { + gasLimit: config.deployGasLimit, + }) + } + const instanceFactory = await ethers.getContractAt('InstanceFactory', contracts.factoryContract.address) // deploy proposal await tornToken.connect(tornWhale).transfer(sender.address, config.creationFee) diff --git a/yarn.lock b/yarn.lock index 73802ed..69b1d7e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5275,9 +5275,9 @@ blake2b-wasm@^1.1.0: dependencies: nanoassert "^1.0.0" -"blake2b-wasm@git+https://github.com/jbaylina/blake2b-wasm.git": +"blake2b-wasm@https://github.com/jbaylina/blake2b-wasm.git": version "2.1.0" - resolved "git+https://github.com/jbaylina/blake2b-wasm.git#0d5f024b212429c7f50a7f533aa3a2406b5b42b3" + resolved "https://github.com/jbaylina/blake2b-wasm.git#0d5f024b212429c7f50a7f533aa3a2406b5b42b3" dependencies: nanoassert "^1.0.0" @@ -17429,9 +17429,9 @@ tornado-governance@^1.0.3: "@openzeppelin/upgrades-core" "^1.0.1" torn-token "^1.0.0" -"tornado-relayer-registry@https://github.com/tornadocash/tornado-relayer-registry.git": +"tornado-relayer-registry@https://github.com/Rezan-vm/tornado-relayer-registry.git": version "1.0.0" - resolved "https://github.com/tornadocash/tornado-relayer-registry.git#a5bdbdb4cd44d3951ef6445cce027ee06b5d3400" + resolved "https://github.com/Rezan-vm/tornado-relayer-registry.git#c462d274778e57008414efe9e432dbc03bfbf739" dependencies: "@openzeppelin/contracts" "3.2.0" "@openzeppelin/hardhat-upgrades" "1.10.0" @@ -17444,6 +17444,7 @@ tornado-governance@^1.0.3: tornado-anonymity-mining "^2.1.5" tornado-cli "^0.0.1" tornado-governance "2.0.0" + tornado-trees "^0.0.11" tornado-trees@^0.0.11: version "0.0.11"