Complete deployment script
This commit is contained in:
parent
36798e04f2
commit
a2e8e5aa80
2
.gitignore
vendored
2
.gitignore
vendored
@ -12,3 +12,5 @@ node_modules
|
||||
# solidity-coverage files
|
||||
/coverage
|
||||
/coverage.json
|
||||
|
||||
/flatten
|
10
contracts/Classic/Echoer.sol
Normal file
10
contracts/Classic/Echoer.sol
Normal file
@ -0,0 +1,10 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
contract Echoer {
|
||||
event Echo(address indexed who, bytes data);
|
||||
|
||||
function echo(bytes calldata _data) external {
|
||||
emit Echo(msg.sender, _data);
|
||||
}
|
||||
}
|
@ -16,10 +16,11 @@ import { IVerifier, IHasher, ERC20Tornado } from "./ERC20Tornado.sol";
|
||||
import { IERC20 } from "./interfaces/IERC20.sol";
|
||||
|
||||
contract cTornado is ERC20Tornado {
|
||||
address public immutable governance = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce;
|
||||
address public immutable governance;
|
||||
IERC20 public immutable comp;
|
||||
|
||||
constructor(
|
||||
address _governance,
|
||||
IERC20 _comp,
|
||||
IVerifier _verifier,
|
||||
IHasher _hasher,
|
||||
@ -28,6 +29,7 @@ contract cTornado is ERC20Tornado {
|
||||
IERC20 _token
|
||||
) ERC20Tornado(_verifier, _hasher, _denomination, _merkleTreeHeight, _token) {
|
||||
require(address(_comp) != address(0), "Invalid COMP token address");
|
||||
governance = _governance;
|
||||
comp = _comp;
|
||||
}
|
||||
|
||||
|
@ -5,10 +5,7 @@ pragma experimental ABIEncoderV2;
|
||||
|
||||
import { UniswapV3OracleHelper } from "./libraries/UniswapV3OracleHelper.sol";
|
||||
import { SafeMath } from "@openzeppelin/contracts-v3/math/SafeMath.sol";
|
||||
|
||||
import { IERC20 } from "@openzeppelin/contracts-v3/token/ERC20/IERC20.sol";
|
||||
import { ITornadoInstance } from "./interfaces/ITornadoInstance.sol";
|
||||
import { InstanceRegistry } from "./InstanceRegistry.sol";
|
||||
import { IERC20, InstanceRegistry, ITornadoInstance } from "./InstanceRegistry.sol";
|
||||
|
||||
/// @dev contract which calculates the fee for each pool
|
||||
contract FeeManager {
|
||||
|
49
contracts/Governance/GasCompensationVault.sol
Normal file
49
contracts/Governance/GasCompensationVault.sol
Normal file
@ -0,0 +1,49 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
/**
|
||||
* @notice this contract should store ether for gas compensations and also retrieve the basefee
|
||||
* @dev modified for non constant governance address and simpler code
|
||||
* */
|
||||
contract GasCompensationVault {
|
||||
address public immutable GovernanceAddress;
|
||||
|
||||
modifier onlyGovernance() {
|
||||
require(msg.sender == GovernanceAddress, "only gov");
|
||||
_;
|
||||
}
|
||||
|
||||
constructor(address _governance) {
|
||||
GovernanceAddress = _governance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice function to compensate gas by sending amount eth to a recipient
|
||||
* @param recipient address to receive amount eth
|
||||
* @param gasAmount the amount of gas to be compensated
|
||||
* */
|
||||
function compensateGas(address recipient, uint256 gasAmount) external onlyGovernance {
|
||||
uint256 vaultBalance = address(this).balance;
|
||||
uint256 toCompensate = gasAmount * block.basefee;
|
||||
if (vaultBalance == 0) return;
|
||||
//payable(recipient).send((toCompensate > vaultBalance) ? vaultBalance : toCompensate);
|
||||
(bool success, ) = recipient.call{ value: (toCompensate > vaultBalance) ? vaultBalance : toCompensate }('');
|
||||
require(success, "compensate gas failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice function to withdraw compensate eth back to governance
|
||||
* @param amount the amount of eth to withdraw back to governance
|
||||
* */
|
||||
function withdrawToGovernance(uint256 amount) external onlyGovernance {
|
||||
uint256 vaultBalance = address(this).balance;
|
||||
//require(GovernanceAddress.sendEther((amount > vaultBalance) ? vaultBalance : amount), "pay fail");
|
||||
(bool success, ) = GovernanceAddress.call{ value: (amount > vaultBalance) ? vaultBalance : amount }('');
|
||||
require(success, "pay fail");
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice receive ether function, does nothing but receive ether
|
||||
* */
|
||||
receive() external payable {}
|
||||
}
|
@ -7,7 +7,6 @@ import { Initializable } from "@openzeppelin/contracts-v3/proxy/Initializable.so
|
||||
import { IERC20 } from "@openzeppelin/contracts-v3/token/ERC20/IERC20.sol";
|
||||
import { SafeERC20 } from "@openzeppelin/contracts-v3/token/ERC20/SafeERC20.sol";
|
||||
import { ITornadoInstance } from "./interfaces/ITornadoInstance.sol";
|
||||
import { FeeManager } from "./FeeManager.sol";
|
||||
|
||||
interface ITornadoRouter {
|
||||
function approveExactToken(IERC20 _token, address _spender, uint256 _amount) external;
|
||||
|
53
contracts/Governance/Testnet/TestnetAdminProxy.sol
Normal file
53
contracts/Governance/Testnet/TestnetAdminProxy.sol
Normal file
@ -0,0 +1,53 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.6.12;
|
||||
|
||||
import { OwnableLibrary } from "../libraries/OwnableLibrary.sol";
|
||||
import { TransparentUpgradeableProxy } from "@openzeppelin/contracts-v3/proxy/TransparentUpgradeableProxy.sol";
|
||||
|
||||
/**
|
||||
* @dev Enables testnet contracts to be upgraded by the governance and maintainer, since we don't want to waste time
|
||||
*/
|
||||
contract TestnetAdminProxy is TransparentUpgradeableProxy {
|
||||
modifier onlyOwner {
|
||||
require(OwnableLibrary.getOwner() == msg.sender, "Not an owner");
|
||||
_;
|
||||
}
|
||||
|
||||
constructor(
|
||||
address _logic,
|
||||
address _admin,
|
||||
bytes memory _data
|
||||
) public payable TransparentUpgradeableProxy(_logic, _admin, _data) {
|
||||
OwnableLibrary.setOwner(msg.sender);
|
||||
}
|
||||
|
||||
function getCurrentOwner() external view returns (address) {
|
||||
return OwnableLibrary.getOwner();
|
||||
}
|
||||
|
||||
function changeOwner(address newOwner) external onlyOwner {
|
||||
OwnableLibrary.setOwner(newOwner);
|
||||
}
|
||||
|
||||
function upgradeToOwner(address newImplementation) external onlyOwner {
|
||||
_upgradeTo(newImplementation);
|
||||
}
|
||||
|
||||
function callToOwner(address target, bytes memory data) external payable onlyOwner {
|
||||
(bool success, bytes memory returnData) = target.call{ value: msg.value }(data);
|
||||
if (!success) {
|
||||
assembly {
|
||||
revert(add(32, returnData), mload(returnData))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function delegateToOwner(address target, bytes memory data) external payable onlyOwner {
|
||||
(bool success, bytes memory returnData) = target.delegatecall(data);
|
||||
if (!success) {
|
||||
assembly {
|
||||
revert(add(32, returnData), mload(returnData))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
49
contracts/Governance/Testnet/TestnetGovernanceProxy.sol
Normal file
49
contracts/Governance/Testnet/TestnetGovernanceProxy.sol
Normal file
@ -0,0 +1,49 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.6.12;
|
||||
|
||||
import { OwnableLibrary } from "../libraries/OwnableLibrary.sol";
|
||||
import { LoopbackProxy } from "../LoopbackProxy.sol";
|
||||
|
||||
/**
|
||||
* @dev Enables testnet contracts to be upgraded by the maintainer, since we don't want to waste time
|
||||
*/
|
||||
contract TestnetGovernanceProxy is LoopbackProxy {
|
||||
modifier onlyOwner {
|
||||
require(OwnableLibrary.getOwner() == msg.sender, "Not an owner");
|
||||
_;
|
||||
}
|
||||
|
||||
constructor(address _logic, bytes memory _data) public payable LoopbackProxy(_logic, _data) {
|
||||
OwnableLibrary.setOwner(msg.sender);
|
||||
}
|
||||
|
||||
function getCurrentOwner() external view returns (address) {
|
||||
return OwnableLibrary.getOwner();
|
||||
}
|
||||
|
||||
function changeOwner(address newOwner) external onlyOwner {
|
||||
OwnableLibrary.setOwner(newOwner);
|
||||
}
|
||||
|
||||
function upgradeToOwner(address newImplementation) external onlyOwner {
|
||||
_upgradeTo(newImplementation);
|
||||
}
|
||||
|
||||
function callToOwner(address target, bytes memory data) external payable onlyOwner {
|
||||
(bool success, bytes memory returnData) = target.call{ value: msg.value }(data);
|
||||
if (!success) {
|
||||
assembly {
|
||||
revert(add(32, returnData), mload(returnData))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function delegateToOwner(address target, bytes memory data) external payable onlyOwner {
|
||||
(bool success, bytes memory returnData) = target.delegatecall(data);
|
||||
if (!success) {
|
||||
assembly {
|
||||
revert(add(32, returnData), mload(returnData))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.6.12;
|
||||
|
||||
import { OwnableLibrary } from "../libraries/OwnableLibrary.sol";
|
||||
import { LoopbackProxy } from "../LoopbackProxy.sol";
|
||||
|
||||
/**
|
||||
* @dev Enables testnet contracts to be upgraded by the maintainer, since we don't want to waste time
|
||||
*/
|
||||
contract TestnetProxy is LoopbackProxy {
|
||||
modifier onlyOwner {
|
||||
require(OwnableLibrary.getOwner() == msg.sender, "Not an owner");
|
||||
_;
|
||||
}
|
||||
|
||||
constructor(address _logic, bytes memory _data) public payable LoopbackProxy(_logic, _data) {
|
||||
OwnableLibrary.setOwner(msg.sender);
|
||||
}
|
||||
|
||||
function upgradeToOwner(address newImplementation) external onlyOwner {
|
||||
_upgradeTo(newImplementation);
|
||||
}
|
||||
}
|
@ -9,8 +9,13 @@ import { SafeERC20 } from "@openzeppelin/contracts-v3/token/ERC20/SafeERC20.sol"
|
||||
contract TornadoVault {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
address internal constant TornTokenAddress = 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C;
|
||||
address internal constant GovernanceAddress = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce;
|
||||
address internal immutable TornTokenAddress;
|
||||
address internal immutable GovernanceAddress;
|
||||
|
||||
constructor(address _torn, address _governance) public {
|
||||
TornTokenAddress = _torn;
|
||||
GovernanceAddress = _governance;
|
||||
}
|
||||
|
||||
/// @notice withdraws TORN from the contract
|
||||
/// @param amount amount to withdraw
|
||||
|
@ -1,6 +1,37 @@
|
||||
import { HardhatUserConfig } from "hardhat/config";
|
||||
import "@nomicfoundation/hardhat-toolbox";
|
||||
import "hardhat-storage-layout";
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import process from 'process';
|
||||
import { task, HardhatUserConfig } from 'hardhat/config';
|
||||
import '@nomicfoundation/hardhat-toolbox';
|
||||
import '@nomicfoundation/hardhat-ethers';
|
||||
import 'hardhat-storage-layout';
|
||||
|
||||
task('flatten:all', 'Flatten all contracts each file under flatten directory')
|
||||
.setAction(async (taskArgs, hre) => {
|
||||
const allFilesAndFolders = fs.readdirSync('contracts', { recursive: true }) as Array<string>;
|
||||
const allFolders = allFilesAndFolders.filter(f => fs.statSync(path.join('contracts', f)).isDirectory());
|
||||
const allFiles = allFilesAndFolders.filter(f => !allFolders.includes(f));
|
||||
|
||||
fs.rmSync('flatten', { force: true, recursive: true });
|
||||
fs.mkdirSync('flatten');
|
||||
allFolders.forEach(f => {
|
||||
fs.mkdirSync(path.join('flatten', f), { recursive: true });
|
||||
});
|
||||
|
||||
await Promise.all(allFiles.map(async (f) => {
|
||||
const contract = path.join('contracts', f);
|
||||
const contractTo = path.join('flatten', f);
|
||||
try {
|
||||
const flatten = await hre.run('flatten:get-flattened-sources', { files: [contract] });
|
||||
fs.writeFileSync(contractTo, flatten);
|
||||
console.log(`Wrote ${contractTo} contract`);
|
||||
} catch (e) {
|
||||
// Catching circular contracts
|
||||
console.log(`Failed to write ${contractTo} contract`);
|
||||
console.log(e);
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
const config: HardhatUserConfig = {
|
||||
defaultNetwork: 'hardhat',
|
||||
@ -28,6 +59,22 @@ const config: HardhatUserConfig = {
|
||||
],
|
||||
},
|
||||
networks: {
|
||||
develop: {
|
||||
url: process.env.RPC_URL || '',
|
||||
accounts: {
|
||||
mnemonic: process.env.MNEMONIC || 'test test test test test test test test test test test junk',
|
||||
initialIndex: Number(process.env.MNEMONIC_INDEX) || 0,
|
||||
},
|
||||
gasPrice: 50000,
|
||||
},
|
||||
sepolia: {
|
||||
url: process.env.RPC_URL || 'https://rpc.sepolia.org',
|
||||
accounts: {
|
||||
mnemonic: process.env.MNEMONIC || 'test test test test test test test test test test test junk',
|
||||
initialIndex: Number(process.env.MNEMONIC_INDEX) || 0,
|
||||
},
|
||||
gasPrice: 50000,
|
||||
},
|
||||
hardhat: {},
|
||||
},
|
||||
};
|
||||
|
@ -4,10 +4,13 @@
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"lint": "eslint test --ext .ts --fix"
|
||||
"compile": "hardhat compile && hardhat flatten:all",
|
||||
"deploy": "hardhat run ./scripts/deploy.ts",
|
||||
"lint": "eslint . --ext .ts --fix"
|
||||
},
|
||||
"files": [
|
||||
"contracts",
|
||||
"scripts",
|
||||
"hardhat.config.ts",
|
||||
"README.md",
|
||||
"tsconfig.json",
|
||||
|
355
scripts/deploy.ts
Normal file
355
scripts/deploy.ts
Normal file
@ -0,0 +1,355 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import hardhat, { ethers } from 'hardhat';
|
||||
import {
|
||||
type ERC20Mock,
|
||||
type InstanceRegistry,
|
||||
ERC20Mock__factory,
|
||||
TORN__factory,
|
||||
Governance__factory,
|
||||
ETHTornado__factory,
|
||||
ERC20Tornado__factory,
|
||||
Vesting__factory,
|
||||
TestnetGovernanceProxy__factory,
|
||||
TestnetAdminProxy__factory,
|
||||
GasCompensationVault__factory,
|
||||
InstanceRegistry__factory,
|
||||
GovernanceProposalStateUpgrade__factory,
|
||||
RelayerRegistry__factory,
|
||||
TornadoStakingRewards__factory,
|
||||
TornadoRouter__factory,
|
||||
TornadoVault__factory,
|
||||
Echoer__factory,
|
||||
TestnetFeeManager__factory,
|
||||
} from '../typechain-types';
|
||||
import type { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers';
|
||||
const {
|
||||
ZeroAddress,
|
||||
parseEther,
|
||||
deployContract
|
||||
} = ethers;
|
||||
|
||||
type contracts = {
|
||||
[key in string]: {
|
||||
DAI: string,
|
||||
ens: string,
|
||||
}
|
||||
}
|
||||
|
||||
const contracts: contracts = {
|
||||
hardhat: {
|
||||
DAI: '',
|
||||
ens: '',
|
||||
},
|
||||
develop: {
|
||||
DAI: '',
|
||||
ens: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
|
||||
},
|
||||
sepolia: {
|
||||
// https://staging.aave.com/faucet/
|
||||
DAI: '0xFF34B3d4Aee8ddCd6F9AFFFB6Fe49bD371b8a357',
|
||||
ens: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
|
||||
}
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const toFixedHex = (number: number, length = 32) => {
|
||||
return '0x' + BigInt(number).toString(16).padStart(length * 2, '0');
|
||||
};
|
||||
|
||||
async function deployHasher(owner: SignerWithAddress) {
|
||||
const bytecode = fs.readFileSync(path.join(__dirname, './hasherBytecode.txt'), { encoding: 'utf8' });
|
||||
|
||||
const txReceipt = await owner.sendTransaction({ data: bytecode }).then(t => t.wait());
|
||||
|
||||
return txReceipt?.contractAddress as unknown as string;
|
||||
}
|
||||
|
||||
async function deployInstances() {
|
||||
const [owner] = await ethers.getSigners();
|
||||
const { DAI: daiAddress } = contracts[hardhat.network.name];
|
||||
|
||||
let DAI: ERC20Mock;
|
||||
|
||||
if (!daiAddress) {
|
||||
DAI = await new ERC20Mock__factory(owner).deploy();
|
||||
await DAI.waitForDeployment();
|
||||
|
||||
await DAI.mint(owner.address, parseEther('100000000')).then(t => t.wait());
|
||||
} else {
|
||||
DAI = ERC20Mock__factory.connect(daiAddress, owner);
|
||||
}
|
||||
|
||||
const Hasher = await deployHasher(owner);
|
||||
|
||||
const Verifier = await deployContract('Verifier');
|
||||
await Verifier.waitForDeployment();
|
||||
|
||||
const ETHTornadoFactory = new ETHTornado__factory(owner);
|
||||
|
||||
const ETHTornado1 = await ETHTornadoFactory.deploy(Verifier.target, Hasher, parseEther('0.1'), 20);
|
||||
await ETHTornado1.waitForDeployment();
|
||||
const ETHTornado2 = await ETHTornadoFactory.deploy(Verifier.target, Hasher, parseEther('1'), 20);
|
||||
await ETHTornado2.waitForDeployment();
|
||||
const ETHTornado3 = await ETHTornadoFactory.deploy(Verifier.target, Hasher, parseEther('10'), 20);
|
||||
await ETHTornado3.waitForDeployment();
|
||||
const ETHTornado4 = await ETHTornadoFactory.deploy(Verifier.target, Hasher, parseEther('100'), 20);
|
||||
await ETHTornado4.waitForDeployment();
|
||||
|
||||
// Check if deposit works
|
||||
// console.log(await ETHTornado1.deposit(toFixedHex(42), { value: parseEther('0.1') }).then(t => t.wait()))
|
||||
|
||||
const DAITornadoFactory = new ERC20Tornado__factory(owner);
|
||||
|
||||
const DAITornado1 = await DAITornadoFactory.deploy(Verifier.target, Hasher, parseEther('100'), 20, DAI.target);
|
||||
await DAITornado1.waitForDeployment();
|
||||
const DAITornado2 = await DAITornadoFactory.deploy(Verifier.target, Hasher, parseEther('1000'), 20, DAI.target);
|
||||
await DAITornado2.waitForDeployment();
|
||||
const DAITornado3 = await DAITornadoFactory.deploy(Verifier.target, Hasher, parseEther('10000'), 20, DAI.target);
|
||||
await DAITornado3.waitForDeployment();
|
||||
const DAITornado4 = await DAITornadoFactory.deploy(Verifier.target, Hasher, parseEther('100000'), 20, DAI.target);
|
||||
await DAITornado4.waitForDeployment();
|
||||
|
||||
const ethInstance = {
|
||||
isERC20: false,
|
||||
token: ZeroAddress,
|
||||
state: 1,
|
||||
uniswapPoolSwappingFee: 0,
|
||||
protocolFeePercentage: 0,
|
||||
};
|
||||
|
||||
const daiInstance = {
|
||||
isERC20: true,
|
||||
token: DAI.target,
|
||||
state: 1,
|
||||
uniswapPoolSwappingFee: 3000,
|
||||
protocolFeePercentage: 0,
|
||||
};
|
||||
|
||||
const instances = [
|
||||
{
|
||||
addr: ETHTornado1.target,
|
||||
instance: ethInstance,
|
||||
},
|
||||
{
|
||||
addr: DAITornado2.target,
|
||||
instance: {
|
||||
...ethInstance,
|
||||
protocolFeePercentage: 30,
|
||||
},
|
||||
},
|
||||
{
|
||||
addr: ETHTornado3.target,
|
||||
instance: {
|
||||
...ethInstance,
|
||||
protocolFeePercentage: 30,
|
||||
},
|
||||
},
|
||||
{
|
||||
addr: ETHTornado4.target,
|
||||
instance: {
|
||||
...ethInstance,
|
||||
protocolFeePercentage: 30,
|
||||
},
|
||||
},
|
||||
{
|
||||
addr: DAITornado1.target,
|
||||
instance: daiInstance,
|
||||
},
|
||||
{
|
||||
addr: DAITornado2.target,
|
||||
instance: daiInstance,
|
||||
},
|
||||
{
|
||||
addr: DAITornado3.target,
|
||||
instance: {
|
||||
...daiInstance,
|
||||
protocolFeePercentage: 30,
|
||||
},
|
||||
},
|
||||
{
|
||||
addr: DAITornado4.target,
|
||||
instance: {
|
||||
...daiInstance,
|
||||
protocolFeePercentage: 30,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
console.log({
|
||||
DAI: DAI.target,
|
||||
Hasher: Hasher,
|
||||
Verifier: Verifier.target,
|
||||
instances,
|
||||
});
|
||||
|
||||
return {
|
||||
DAI,
|
||||
Hasher,
|
||||
Verifier,
|
||||
instances,
|
||||
};
|
||||
}
|
||||
|
||||
async function deployGovernance(instances: InstanceRegistry.TornadoStruct[]): Promise<void> {
|
||||
const [owner] = await ethers.getSigners();
|
||||
const { ENS: ensAddress } = contracts[hardhat.network.name];
|
||||
|
||||
// Deploy V1 logic contact first
|
||||
const GovernanceV1 = await new Governance__factory(owner).deploy();
|
||||
await GovernanceV1.waitForDeployment();
|
||||
|
||||
// This is what almost every contract would need for constructor args
|
||||
const GovernanceProxy = await new TestnetGovernanceProxy__factory(owner).deploy(GovernanceV1.target, '0x');
|
||||
await GovernanceProxy.waitForDeployment();
|
||||
|
||||
const TORN = await new TORN__factory(owner).deploy(
|
||||
GovernanceProxy.target,
|
||||
0,
|
||||
[
|
||||
{
|
||||
to: owner.address,
|
||||
amount: parseEther('10000000')
|
||||
}
|
||||
]
|
||||
);
|
||||
await TORN.waitForDeployment();
|
||||
|
||||
// Initialize governance v1 with TORN address
|
||||
await (Governance__factory.connect(GovernanceProxy.target as string, owner)).initialize(TORN.target).then(t => t.wait());
|
||||
|
||||
// Create governance vesting contract
|
||||
const GovernanceVesting = await new Vesting__factory(owner).deploy(
|
||||
TORN.target,
|
||||
GovernanceProxy.target,
|
||||
0,
|
||||
3,
|
||||
60
|
||||
);
|
||||
await GovernanceVesting.waitForDeployment();
|
||||
|
||||
await TORN.transfer(GovernanceVesting.target, parseEther('2500000')).then(t => t.wait());
|
||||
|
||||
// Deploy other governance contracts
|
||||
const ProxyFactory = new TestnetAdminProxy__factory(owner);
|
||||
|
||||
// Deploy gas compensation vault
|
||||
const GasCompensationVault = await new GasCompensationVault__factory(owner).deploy(GovernanceProxy.target);
|
||||
await GasCompensationVault.waitForDeployment();
|
||||
|
||||
// Deploy user vault
|
||||
const TornadoVault = await new TornadoVault__factory(owner).deploy(TORN.target, GovernanceProxy.target);
|
||||
await TornadoVault.waitForDeployment();
|
||||
|
||||
// Deploy instance registry
|
||||
const InstanceRegistryImpl = await new InstanceRegistry__factory(owner).deploy(GovernanceProxy.target);
|
||||
await InstanceRegistryImpl.waitForDeployment();
|
||||
|
||||
const InstanceRegistryProxy = await ProxyFactory.deploy(InstanceRegistryImpl.target, GovernanceProxy.target, '0x');
|
||||
await InstanceRegistryProxy.waitForDeployment();
|
||||
|
||||
// Deploy FeeManager
|
||||
const FeeManagerImpl = await new TestnetFeeManager__factory(owner).deploy(TORN.target, GovernanceProxy.target, InstanceRegistryProxy.target);
|
||||
await FeeManagerImpl.waitForDeployment();
|
||||
|
||||
const FeeManagerProxy = await ProxyFactory.deploy(FeeManagerImpl.target, GovernanceProxy.target, '0x');
|
||||
await FeeManagerProxy.waitForDeployment();
|
||||
|
||||
// Deploy RelayerRegistry & TornadoStakingRewards
|
||||
const RelayerRegistryMock = await new RelayerRegistry__factory(owner).deploy(
|
||||
TORN.target,
|
||||
GovernanceProxy.target,
|
||||
ensAddress || ZeroAddress,
|
||||
ZeroAddress, // Use this as zero address as we don't know the proxy address yet
|
||||
FeeManagerProxy.target,
|
||||
);
|
||||
await RelayerRegistryMock.waitForDeployment();
|
||||
|
||||
const RelayerRegistryProxy = await ProxyFactory.deploy(RelayerRegistryMock.target, GovernanceProxy.target, '0x');
|
||||
await RelayerRegistryProxy.waitForDeployment();
|
||||
|
||||
const TornadoStakingRewardsImpl = await new TornadoStakingRewards__factory(owner).deploy(
|
||||
GovernanceProxy.target,
|
||||
TORN.target,
|
||||
RelayerRegistryProxy.target
|
||||
);
|
||||
await TornadoStakingRewardsImpl.waitForDeployment();
|
||||
|
||||
const TornadoStakingRewardsProxy = await ProxyFactory.deploy(TornadoStakingRewardsImpl.target, GovernanceProxy.target, '0x');
|
||||
await TornadoStakingRewardsProxy.waitForDeployment();
|
||||
|
||||
const RelayerRegistryImpl = await new RelayerRegistry__factory(owner).deploy(
|
||||
TORN.target,
|
||||
GovernanceProxy.target,
|
||||
ensAddress || ZeroAddress,
|
||||
TornadoStakingRewardsProxy.target,
|
||||
FeeManagerProxy.target,
|
||||
);
|
||||
await RelayerRegistryImpl.waitForDeployment();
|
||||
|
||||
await (TestnetAdminProxy__factory.connect(RelayerRegistryProxy.target as string, owner)).upgradeToOwner(RelayerRegistryImpl.target).then(t => t.wait());
|
||||
|
||||
// Deploy Echoer
|
||||
const Echoer = await new Echoer__factory(owner).deploy();
|
||||
await Echoer.waitForDeployment();
|
||||
|
||||
// Deploy TornadoRouter
|
||||
const TornadoRouter = await new TornadoRouter__factory(owner).deploy(
|
||||
GovernanceProxy.target,
|
||||
InstanceRegistryProxy.target,
|
||||
RelayerRegistryProxy.target
|
||||
);
|
||||
await TornadoRouter.waitForDeployment();
|
||||
|
||||
// Initialize InstanceRegistry
|
||||
await (InstanceRegistry__factory.connect(InstanceRegistryProxy.target as string, owner)).initialize(
|
||||
instances,
|
||||
TornadoRouter.target
|
||||
).then(t => t.wait());
|
||||
|
||||
// Initialize RelayerRegistry
|
||||
await (RelayerRegistry__factory.connect(RelayerRegistryProxy.target as string, owner)).initialize(
|
||||
TornadoRouter.target
|
||||
).then(t => t.wait());
|
||||
|
||||
// Upgrade Governance
|
||||
const GovernanceV5 = await new GovernanceProposalStateUpgrade__factory(owner).deploy(
|
||||
TornadoStakingRewardsProxy.target,
|
||||
GasCompensationVault.target,
|
||||
TornadoVault.target
|
||||
);
|
||||
await GovernanceV5.waitForDeployment();
|
||||
|
||||
await (TestnetGovernanceProxy__factory.connect(GovernanceProxy.target as string, owner)).upgradeToOwner(GovernanceV5.target).then(t => t.wait());
|
||||
|
||||
// Finalize contracts
|
||||
await owner.sendTransaction({ to: GasCompensationVault.target, value: parseEther('0.1') }).then(t => t.wait());
|
||||
|
||||
console.log({
|
||||
TORN: TORN.target,
|
||||
GovernanceProxy: GovernanceProxy.target,
|
||||
GovernanceV1: GovernanceV1.target,
|
||||
GovernanceV5: GovernanceV5.target,
|
||||
GovernanceVesting: GovernanceVesting.target,
|
||||
GasCompensationVault: GasCompensationVault.target,
|
||||
TornadoVault: TornadoVault.target,
|
||||
InstanceRegistryProxy: InstanceRegistryProxy.target,
|
||||
InstanceRegistryImpl: InstanceRegistryImpl.target,
|
||||
FeeManagerProxy: FeeManagerProxy.target,
|
||||
FeeManagerImpl: FeeManagerImpl.target,
|
||||
RelayerRegistryProxy: RelayerRegistryProxy.target,
|
||||
RelayerRegistryImpl: RelayerRegistryImpl.target,
|
||||
RelayerRegistryMock: RelayerRegistryMock.target,
|
||||
TornadoStakingRewardsProxy: TornadoStakingRewardsProxy.target,
|
||||
TornadoStakingRewardsImpl: TornadoStakingRewardsImpl.target,
|
||||
TornadoRouter: TornadoRouter.target,
|
||||
Echoer: Echoer.target,
|
||||
});
|
||||
}
|
||||
|
||||
async function deploy() {
|
||||
const { instances } = await deployInstances();
|
||||
await deployGovernance(instances);
|
||||
}
|
||||
|
||||
deploy();
|
1
scripts/hasherBytecode.txt
Normal file
1
scripts/hasherBytecode.txt
Normal file
File diff suppressed because one or more lines are too long
@ -9,6 +9,7 @@
|
||||
"resolveJsonModule": true,
|
||||
"types": ["@types/node"]
|
||||
},
|
||||
"include": ["test/**/*"],
|
||||
"exclude": ["node_modules"]
|
||||
"include": ["./scripts", "./test", "./typechain-types"],
|
||||
"exclude": ["node_modules"],
|
||||
"files": ["./hardhat.config.ts"]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user