mirror of
https://github.com/tornadocash/tornado-pool-factory
synced 2024-02-02 15:04:08 +01:00
automatically detect n of instances
coverage try build fix use create2 add core repo
This commit is contained in:
parent
96592be181
commit
9ff6229ebd
@ -3,6 +3,7 @@ goerli_rpc_key=
|
||||
mainnet_rpc_key=
|
||||
goerli_account_pk=
|
||||
mainnet_account_pk=
|
||||
use_latest_block=false
|
||||
|
||||
PROXY=0x722122dF12D4e14e13Ac3b6895a86e84145b6967
|
||||
DEPLOYER=0xCEe71753C9820f063b38FDbE4cFDAf1d3D928A80
|
||||
|
@ -1,3 +1,6 @@
|
||||
use_latest_block=false
|
||||
|
||||
PROXY=0x722122dF12D4e14e13Ac3b6895a86e84145b6967
|
||||
DEPLOYER=0xCEe71753C9820f063b38FDbE4cFDAf1d3D928A80
|
||||
HASHER=0x83584f83f26aF4eDDA9CBe8C730bc87C364b28fe
|
||||
VERIFIER=0xce172ce1F20EC0B3728c9965470eaf994A03557A
|
||||
|
3
.github/workflows/build.js.yml
vendored
3
.github/workflows/build.js.yml
vendored
@ -25,8 +25,7 @@ jobs:
|
||||
- run: cp .env.example.workflow .env
|
||||
- run: yarn prettier:fix
|
||||
- run: yarn lint
|
||||
- run: yarn test test/test_proposal_with_factory.js
|
||||
- run: yarn test test/test_proposal_with_factory2.js
|
||||
- run: yarn test
|
||||
|
||||
- name: Generate coverage
|
||||
run: yarn coverage
|
||||
|
@ -4,5 +4,11 @@ module.exports = {
|
||||
'tornado_proxy/ITornadoTrees.sol',
|
||||
'tornado_proxy/ITornadoInstance.sol',
|
||||
'ERC20TornadoVirtual.sol',
|
||||
'denomination_templates/Add1Instance.sol',
|
||||
'denomination_templates/Add2Instances.sol',
|
||||
'denomination_templates/Add3Instances.sol',
|
||||
'denomination_templates/Add4Instances.sol',
|
||||
'denomination_templates/Add5Instances.sol',
|
||||
'denomination_templates/Add6Instances.sol',
|
||||
],
|
||||
}
|
||||
|
48
README.md
48
README.md
@ -1,12 +1,14 @@
|
||||
# Tornado Instances
|
||||
|
||||
[![build](https://img.shields.io/github/workflow/status/mirru2532/tornado-instances/build)](https://github.com/h-ivor/tornado-instances/actions) [![Coveralls](https://img.shields.io/coveralls/github/mirru2352/tornado-instances)](https://coveralls.io/github/mirru2352/tornado-instances)
|
||||
[![build](https://img.shields.io/github/workflow/status/mirru2532/tornado-instances/build)](https://github.com/h-ivor/tornado-instances/actions) [![Coveralls](https://img.shields.io/coveralls/github/mirru2532/tornado-instances)](https://coveralls.io/github/mirru2532/tornado-instances)
|
||||
|
||||
## About
|
||||
|
||||
This repository serves as a general template for deploying a tornado instance factory, deploying a proposal for the addition of multiple ERC20 tornado instances and proposing the registration of these instances with the Tornado Proxy (0x722122dF12D4e14e13Ac3b6895a86e84145b6967) through governance vote.
|
||||
This repository serves as a general template repository for deploying proposals for governance for the addition of new tornado ERC20 instances to the tornado proxy.
|
||||
|
||||
The scripts should help users do this programmatically, quickly. There are three tasks (scripts). Note that non-task scripts have been deprecated but are still kept for more insight into the working process.
|
||||
The contracts offer a template for the addition of 4 new instances for an ERC20 token (the standard way to add new instances) and can also be slightly modified to add a custom amount. The scripts deploy the contracts.
|
||||
|
||||
The resources folder contains data necessary for the instances to be deployed and must be filled out. They are initially filled out with the RAI instance data.
|
||||
|
||||
### How-To:
|
||||
|
||||
@ -19,7 +21,7 @@ yarn
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Please fill out .env according to the template provided in it.
|
||||
Please fill out .env according to the template provided in it. Please ensure that all of the example values are set to the correct addresses.
|
||||
|
||||
### Testing and running scripts:
|
||||
|
||||
@ -35,26 +37,20 @@ Running **tasks:**
|
||||
|
||||
```bash
|
||||
# a list of yarn scripts specifically for instance deployment
|
||||
"deploy:factory": "yarn hardhat --network mainnet deploy_factory",
|
||||
"deploy:proposal": "yarn hardhat --network mainnet deploy_proposal --factory-address",
|
||||
"deploy:factory:test": "yarn hardhat --network goerli deploy_factory",
|
||||
"deploy:proposal:test": "yarn hardhat --network goerli deploy_proposal --factory-address",
|
||||
"propose": "yarn hardhat --network mainnet propose_proposal --proposal-address"
|
||||
"deploy:proposal:factory": "yarn hardhat --network mainnet deploy_factory_proposal",
|
||||
"deploy:proposal:factory:test": "yarn hardhat --network goerli deploy_factory_proposal",
|
||||
"propose": "yarn hardhat --network mainnet propose_proposal --proposal-address",
|
||||
|
||||
# as an example
|
||||
yarn deploy:factory
|
||||
yarn deploy:proposal:factory
|
||||
|
||||
# to call a specific task
|
||||
yarn hardhat --network <network> <task> <args>
|
||||
```
|
||||
|
||||
Running scripts (deprecated):
|
||||
|
||||
```bash
|
||||
yarn hardhat --network <network> run scripts/<script to run>
|
||||
```
|
||||
|
||||
### Deploying a proposal for an instance update
|
||||
## Deploying a proposal for an instance update
|
||||
|
||||
Open `resources/instances.js`, a single object which generates an instance contains the following fields (RAI as an example):
|
||||
|
||||
@ -62,33 +58,15 @@ Open `resources/instances.js`, a single object which generates an instance conta
|
||||
{
|
||||
tokenAddress: "0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919",
|
||||
denomination: "33333333333333333333",
|
||||
domain: "rai-100.tornadocash.eth",
|
||||
symbol: "RAI",
|
||||
decimals: 18
|
||||
}
|
||||
```
|
||||
|
||||
`denomination` - tokens can only be deposited in certain denominations into instances, the above considers this instance to have a 100$ denomination, assuming RAI at 3$.
|
||||
`domain` - resolves to the address of the instance.
|
||||
Fill out each of these fields for your own token in the `instance.js` file. Please note that these contracts support deployments of exactly 4 denominations, as is the standard with which we have been deploying. If you would like to add more instances, contact me below or modify contracts independently.
|
||||
Fill out each of these fields for your own token in the `instance.js` file. This repo supports the addition of a maximum of 6 instances at once. It will automatically detect how many instances are to use.
|
||||
|
||||
Now find the factory contract address, or deploy one if one has not been deployed (unlikely):
|
||||
|
||||
**If factory not deployed:**
|
||||
|
||||
```bash
|
||||
yarn deploy:factory
|
||||
```
|
||||
|
||||
If testing:
|
||||
|
||||
```bash
|
||||
yarn deploy:factory:test
|
||||
```
|
||||
|
||||
**If factory is already deployed, continue here:**
|
||||
|
||||
And now take the contract address which you should see in the command line interface and add this to:
|
||||
Now find the factory contract address:
|
||||
|
||||
```bash
|
||||
yarn deploy:proposal <factory address>
|
||||
|
@ -44,13 +44,11 @@ contract CreateFactoryAndAddInstancesProposal {
|
||||
|
||||
for (uint256 i = 0; i < 4; i++) {
|
||||
ITornadoInstance instance = ITornadoInstance(instanceFactory.createInstanceClone(denominations(i), token));
|
||||
|
||||
TornadoProxy.Instance memory newInstanceData = TornadoProxy.Instance(
|
||||
true,
|
||||
IERC20(token),
|
||||
TornadoProxy.InstanceState.ENABLED
|
||||
);
|
||||
|
||||
TornadoProxy.Tornado memory tornadoForUpdate = TornadoProxy.Tornado(instance, newInstanceData);
|
||||
|
||||
tornadoProxy.updateInstance(tornadoForUpdate);
|
||||
|
@ -2,35 +2,31 @@
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import "./ERC20TornadoVirtual.sol";
|
||||
import "tornado-core/contracts/ERC20Tornado.sol";
|
||||
|
||||
contract ERC20TornadoCloneable is ERC20Tornado {
|
||||
constructor() ERC20Tornado(IVerifier(address(0)), IHasher(address(0)), 1, 1, IERC20(address(0))) {}
|
||||
constructor(address verifier, address hasher) ERC20Tornado(IVerifier(verifier), IHasher(hasher), 1, 1, IERC20(address(0))) {}
|
||||
|
||||
function init(
|
||||
IVerifier _verifier,
|
||||
IHasher _hasher,
|
||||
uint256 _denomination,
|
||||
uint32 _merkleTreeHeight,
|
||||
IERC20 _token
|
||||
address _token
|
||||
) external {
|
||||
require(address(verifier) == address(0) && address(hasher) == address(0), "already initialized");
|
||||
/// In Constructor: ERC20Tornado from ERC20TornadoVirtual.sol
|
||||
token = _token;
|
||||
/// In Constructor: Tornado from ERC20TornadoVirtual.sol
|
||||
require(denomination == 0 && levels == 0, "already initialized");
|
||||
/// In Constructor: ERC20Tornado
|
||||
token = IERC20(_token);
|
||||
/// In Constructor: Tornado
|
||||
require(_denomination > 0, "denomination should be greater than 0");
|
||||
verifier = _verifier;
|
||||
denomination = _denomination;
|
||||
/// In Constructor: MerkleTreeWithHistory from ERC20TornadoVirtual.sol
|
||||
/// In Constructor: MerkleTreeWithHistory
|
||||
require(_merkleTreeHeight > 0, "_levels should be greater than zero");
|
||||
require(_merkleTreeHeight < 32, "_levels should be less than 32");
|
||||
|
||||
hasher = _hasher;
|
||||
levels = _merkleTreeHeight;
|
||||
|
||||
for (uint32 i = 0; i < _merkleTreeHeight; i++) {
|
||||
filledSubtrees[i] = zeros(i);
|
||||
}
|
||||
|
||||
roots[0] = zeros(_merkleTreeHeight - 1);
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ contract MerkleTreeWithHistory {
|
||||
* ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
|
||||
*/
|
||||
|
||||
import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol";
|
||||
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
||||
|
||||
interface IVerifier {
|
||||
function verifyProof(bytes memory _proof, uint256[6] memory _input) external returns (bool);
|
||||
@ -291,8 +291,8 @@ abstract contract Tornado is MerkleTreeWithHistory, ReentrancyGuard {
|
||||
* ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
|
||||
*/
|
||||
|
||||
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
|
||||
import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol";
|
||||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
|
||||
|
||||
contract ERC20Tornado is Tornado {
|
||||
using SafeERC20 for IERC20;
|
||||
|
@ -2,22 +2,27 @@
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import { Ownable } from "openzeppelin-solidity/contracts/access/Ownable.sol";
|
||||
import { IERC20 } from "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
|
||||
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
|
||||
|
||||
import "openzeppelin-solidity/contracts/proxy/Clones.sol";
|
||||
import "@openzeppelin/contracts/proxy/Clones.sol";
|
||||
import "./ERC20TornadoCloneable.sol";
|
||||
|
||||
contract TornadoInstanceCloneFactory is Ownable {
|
||||
using Clones for address;
|
||||
|
||||
mapping(address => mapping(uint256 => address)) public instanceClones;
|
||||
using Address for address;
|
||||
|
||||
address public implementation;
|
||||
address public verifier;
|
||||
address public hasher;
|
||||
uint32 public merkleTreeHeight;
|
||||
|
||||
event NewVerifierSet(address indexed newVerifier);
|
||||
event NewHasherSet(address indexed newHasher);
|
||||
event NewTreeHeightSet(uint32 indexed newTreeHeight);
|
||||
event NewImplementationSet(address indexed newImplemenentation);
|
||||
event NewInstanceCloneCreated(address indexed clone);
|
||||
|
||||
constructor(
|
||||
address _verifier,
|
||||
address _hasher,
|
||||
@ -26,36 +31,48 @@ contract TornadoInstanceCloneFactory is Ownable {
|
||||
verifier = _verifier;
|
||||
hasher = _hasher;
|
||||
merkleTreeHeight = _merkleTreeHeight;
|
||||
|
||||
ERC20TornadoCloneable implContract = new ERC20TornadoCloneable();
|
||||
ERC20TornadoCloneable implContract = new ERC20TornadoCloneable(_verifier, _hasher);
|
||||
implementation = address(implContract);
|
||||
}
|
||||
|
||||
function setVerifier(address _verifier) external onlyOwner {
|
||||
verifier = _verifier;
|
||||
emit NewVerifierSet(verifier);
|
||||
}
|
||||
|
||||
function setHasher(address _hasher) external onlyOwner {
|
||||
hasher = _hasher;
|
||||
emit NewHasherSet(hasher);
|
||||
}
|
||||
|
||||
function setMerkleTreeHeight(uint32 _merkleTreeHeight) external onlyOwner {
|
||||
merkleTreeHeight = _merkleTreeHeight;
|
||||
emit NewTreeHeightSet(merkleTreeHeight);
|
||||
}
|
||||
|
||||
function setImplementation(address _newImplementation) external onlyOwner {
|
||||
implementation = _newImplementation;
|
||||
emit NewImplementationSet(implementation);
|
||||
}
|
||||
|
||||
function generateNewImplementation() external onlyOwner {
|
||||
implementation = address(new ERC20TornadoCloneable(verifier, hasher));
|
||||
}
|
||||
|
||||
function createInstanceClone(uint256 _denomination, address _token) external onlyOwner returns (address) {
|
||||
require(instanceClones[_token][_denomination] == address(0), "Instance for this denomination already exists");
|
||||
address newImpl = implementation.clone();
|
||||
ERC20TornadoCloneable(newImpl).init(IVerifier(verifier), IHasher(hasher), _denomination, merkleTreeHeight, IERC20(_token));
|
||||
instanceClones[_token][_denomination] = newImpl;
|
||||
return newImpl;
|
||||
bytes32 salt = keccak256(abi.encodePacked(_denomination, _token));
|
||||
|
||||
require(!implementation.predictDeterministicAddress(salt).isContract(), "Instance for this denomination already exists");
|
||||
|
||||
address newClone = implementation.cloneDeterministic(salt);
|
||||
|
||||
emit NewInstanceCloneCreated(newClone);
|
||||
ERC20TornadoCloneable(newClone).init(_denomination, merkleTreeHeight, _token);
|
||||
return newClone;
|
||||
}
|
||||
|
||||
function getInstanceAddress(uint256 _denomination, address _token) external view returns (address) {
|
||||
return instanceClones[_token][_denomination];
|
||||
function getInstanceAddress(uint256 _denomination, address _token) public view returns (address) {
|
||||
bytes32 salt = keccak256(abi.encodePacked(_denomination, _token));
|
||||
return implementation.predictDeterministicAddress(salt);
|
||||
}
|
||||
}
|
||||
|
41
contracts/denomination_templates/Add1Instance.sol
Normal file
41
contracts/denomination_templates/Add1Instance.sol
Normal file
@ -0,0 +1,41 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import "../TornadoInstanceCloneFactory.sol";
|
||||
import "../tornado_proxy/TornadoProxy.sol";
|
||||
|
||||
contract Add1Instance {
|
||||
TornadoInstanceCloneFactory public immutable instanceFactory;
|
||||
address public immutable token;
|
||||
address public immutable proxyAddress;
|
||||
uint256 public immutable denomination;
|
||||
|
||||
event UpdatedInstanceForProxy(address instance, address token, uint256 denomination);
|
||||
|
||||
constructor(
|
||||
address _proxyAddress,
|
||||
address _instanceFactory,
|
||||
uint256 _denomination,
|
||||
address _token
|
||||
) {
|
||||
instanceFactory = TornadoInstanceCloneFactory(_instanceFactory);
|
||||
token = _token;
|
||||
proxyAddress = _proxyAddress;
|
||||
denomination = _denomination;
|
||||
}
|
||||
|
||||
function executeProposal() external {
|
||||
TornadoProxy tornadoProxy = TornadoProxy(proxyAddress);
|
||||
|
||||
ITornadoInstance instance = ITornadoInstance(instanceFactory.createInstanceClone(denomination, token));
|
||||
|
||||
TornadoProxy.Instance memory newInstanceData = TornadoProxy.Instance(true, IERC20(token), TornadoProxy.InstanceState.ENABLED);
|
||||
|
||||
TornadoProxy.Tornado memory tornadoForUpdate = TornadoProxy.Tornado(instance, newInstanceData);
|
||||
|
||||
tornadoProxy.updateInstance(tornadoForUpdate);
|
||||
|
||||
emit UpdatedInstanceForProxy(address(instance), instance.token(), instance.denomination());
|
||||
}
|
||||
}
|
59
contracts/denomination_templates/Add2Instances.sol
Normal file
59
contracts/denomination_templates/Add2Instances.sol
Normal file
@ -0,0 +1,59 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import "../TornadoInstanceCloneFactory.sol";
|
||||
import "../tornado_proxy/TornadoProxy.sol";
|
||||
|
||||
contract Add2Instances {
|
||||
TornadoInstanceCloneFactory public immutable instanceFactory;
|
||||
address public immutable token;
|
||||
address public immutable proxyAddress;
|
||||
|
||||
uint256 public immutable denomination1;
|
||||
uint256 public immutable denomination2;
|
||||
|
||||
event UpdatedInstanceForProxy(address instance, address token, uint256 denomination);
|
||||
|
||||
constructor(
|
||||
address _proxyAddress,
|
||||
address _instanceFactory,
|
||||
uint256[2] memory _denominations,
|
||||
address _token
|
||||
) {
|
||||
instanceFactory = TornadoInstanceCloneFactory(_instanceFactory);
|
||||
token = _token;
|
||||
proxyAddress = _proxyAddress;
|
||||
|
||||
denomination1 = _denominations[0];
|
||||
denomination2 = _denominations[1];
|
||||
}
|
||||
|
||||
function executeProposal() external {
|
||||
TornadoProxy tornadoProxy = TornadoProxy(proxyAddress);
|
||||
|
||||
for (uint256 i = 0; i < 2; i++) {
|
||||
ITornadoInstance instance = ITornadoInstance(instanceFactory.createInstanceClone(denominations(i), token));
|
||||
|
||||
TornadoProxy.Instance memory newInstanceData = TornadoProxy.Instance(
|
||||
true,
|
||||
IERC20(token),
|
||||
TornadoProxy.InstanceState.ENABLED
|
||||
);
|
||||
|
||||
TornadoProxy.Tornado memory tornadoForUpdate = TornadoProxy.Tornado(instance, newInstanceData);
|
||||
|
||||
tornadoProxy.updateInstance(tornadoForUpdate);
|
||||
|
||||
emit UpdatedInstanceForProxy(address(instance), instance.token(), instance.denomination());
|
||||
}
|
||||
}
|
||||
|
||||
function denominations(uint256 index) private view returns (uint256) {
|
||||
if (index > 0) {
|
||||
return denomination2;
|
||||
} else {
|
||||
return denomination1;
|
||||
}
|
||||
}
|
||||
}
|
63
contracts/denomination_templates/Add3Instances.sol
Normal file
63
contracts/denomination_templates/Add3Instances.sol
Normal file
@ -0,0 +1,63 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import "../TornadoInstanceCloneFactory.sol";
|
||||
import "../tornado_proxy/TornadoProxy.sol";
|
||||
|
||||
contract Add3Instances {
|
||||
TornadoInstanceCloneFactory public immutable instanceFactory;
|
||||
address public immutable token;
|
||||
address public immutable proxyAddress;
|
||||
|
||||
uint256 public immutable denomination1;
|
||||
uint256 public immutable denomination2;
|
||||
uint256 public immutable denomination3;
|
||||
|
||||
event UpdatedInstanceForProxy(address instance, address token, uint256 denomination);
|
||||
|
||||
constructor(
|
||||
address _proxyAddress,
|
||||
address _instanceFactory,
|
||||
uint256[3] memory _denominations,
|
||||
address _token
|
||||
) {
|
||||
instanceFactory = TornadoInstanceCloneFactory(_instanceFactory);
|
||||
token = _token;
|
||||
proxyAddress = _proxyAddress;
|
||||
|
||||
denomination1 = _denominations[0];
|
||||
denomination2 = _denominations[1];
|
||||
denomination3 = _denominations[2];
|
||||
}
|
||||
|
||||
function executeProposal() external {
|
||||
TornadoProxy tornadoProxy = TornadoProxy(proxyAddress);
|
||||
|
||||
for (uint256 i = 0; i < 3; i++) {
|
||||
ITornadoInstance instance = ITornadoInstance(instanceFactory.createInstanceClone(denominations(i), token));
|
||||
|
||||
TornadoProxy.Instance memory newInstanceData = TornadoProxy.Instance(
|
||||
true,
|
||||
IERC20(token),
|
||||
TornadoProxy.InstanceState.ENABLED
|
||||
);
|
||||
|
||||
TornadoProxy.Tornado memory tornadoForUpdate = TornadoProxy.Tornado(instance, newInstanceData);
|
||||
|
||||
tornadoProxy.updateInstance(tornadoForUpdate);
|
||||
|
||||
emit UpdatedInstanceForProxy(address(instance), instance.token(), instance.denomination());
|
||||
}
|
||||
}
|
||||
|
||||
function denominations(uint256 index) private view returns (uint256) {
|
||||
if (index > 1) {
|
||||
return denomination3;
|
||||
} else if (index > 0) {
|
||||
return denomination2;
|
||||
} else {
|
||||
return denomination1;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,10 +2,10 @@
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import "./TornadoInstanceCloneFactory.sol";
|
||||
import "./tornado_proxy/TornadoProxy.sol";
|
||||
import "../TornadoInstanceCloneFactory.sol";
|
||||
import "../tornado_proxy/TornadoProxy.sol";
|
||||
|
||||
contract AddWithFactoryProposal {
|
||||
contract Add4Instances {
|
||||
TornadoInstanceCloneFactory public immutable instanceFactory;
|
||||
address public immutable token;
|
||||
address public immutable proxyAddress;
|
71
contracts/denomination_templates/Add5Instances.sol
Normal file
71
contracts/denomination_templates/Add5Instances.sol
Normal file
@ -0,0 +1,71 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import "../TornadoInstanceCloneFactory.sol";
|
||||
import "../tornado_proxy/TornadoProxy.sol";
|
||||
|
||||
contract Add5Instances {
|
||||
TornadoInstanceCloneFactory public immutable instanceFactory;
|
||||
address public immutable token;
|
||||
address public immutable proxyAddress;
|
||||
|
||||
uint256 public immutable denomination1;
|
||||
uint256 public immutable denomination2;
|
||||
uint256 public immutable denomination3;
|
||||
uint256 public immutable denomination4;
|
||||
uint256 public immutable denomination5;
|
||||
|
||||
event UpdatedInstanceForProxy(address instance, address token, uint256 denomination);
|
||||
|
||||
constructor(
|
||||
address _proxyAddress,
|
||||
address _instanceFactory,
|
||||
uint256[5] memory _denominations,
|
||||
address _token
|
||||
) {
|
||||
instanceFactory = TornadoInstanceCloneFactory(_instanceFactory);
|
||||
token = _token;
|
||||
proxyAddress = _proxyAddress;
|
||||
|
||||
denomination1 = _denominations[0];
|
||||
denomination2 = _denominations[1];
|
||||
denomination3 = _denominations[2];
|
||||
denomination4 = _denominations[3];
|
||||
denomination5 = _denominations[4];
|
||||
}
|
||||
|
||||
function executeProposal() external {
|
||||
TornadoProxy tornadoProxy = TornadoProxy(proxyAddress);
|
||||
|
||||
for (uint256 i = 0; i < 5; i++) {
|
||||
ITornadoInstance instance = ITornadoInstance(instanceFactory.createInstanceClone(denominations(i), token));
|
||||
|
||||
TornadoProxy.Instance memory newInstanceData = TornadoProxy.Instance(
|
||||
true,
|
||||
IERC20(token),
|
||||
TornadoProxy.InstanceState.ENABLED
|
||||
);
|
||||
|
||||
TornadoProxy.Tornado memory tornadoForUpdate = TornadoProxy.Tornado(instance, newInstanceData);
|
||||
|
||||
tornadoProxy.updateInstance(tornadoForUpdate);
|
||||
|
||||
emit UpdatedInstanceForProxy(address(instance), instance.token(), instance.denomination());
|
||||
}
|
||||
}
|
||||
|
||||
function denominations(uint256 index) private view returns (uint256) {
|
||||
if (index > 3) {
|
||||
return denomination5;
|
||||
} else if (index > 2) {
|
||||
return denomination4;
|
||||
} else if (index > 1) {
|
||||
return denomination3;
|
||||
} else if (index > 0) {
|
||||
return denomination2;
|
||||
} else {
|
||||
return denomination1;
|
||||
}
|
||||
}
|
||||
}
|
75
contracts/denomination_templates/Add6Instances.sol
Normal file
75
contracts/denomination_templates/Add6Instances.sol
Normal file
@ -0,0 +1,75 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import "../TornadoInstanceCloneFactory.sol";
|
||||
import "../tornado_proxy/TornadoProxy.sol";
|
||||
|
||||
contract Add6Instances {
|
||||
TornadoInstanceCloneFactory public immutable instanceFactory;
|
||||
address public immutable token;
|
||||
address public immutable proxyAddress;
|
||||
|
||||
uint256 public immutable denomination1;
|
||||
uint256 public immutable denomination2;
|
||||
uint256 public immutable denomination3;
|
||||
uint256 public immutable denomination4;
|
||||
uint256 public immutable denomination5;
|
||||
uint256 public immutable denomination6;
|
||||
|
||||
event UpdatedInstanceForProxy(address instance, address token, uint256 denomination);
|
||||
|
||||
constructor(
|
||||
address _proxyAddress,
|
||||
address _instanceFactory,
|
||||
uint256[6] memory _denominations,
|
||||
address _token
|
||||
) {
|
||||
instanceFactory = TornadoInstanceCloneFactory(_instanceFactory);
|
||||
token = _token;
|
||||
proxyAddress = _proxyAddress;
|
||||
|
||||
denomination1 = _denominations[0];
|
||||
denomination2 = _denominations[1];
|
||||
denomination3 = _denominations[2];
|
||||
denomination4 = _denominations[3];
|
||||
denomination5 = _denominations[4];
|
||||
denomination6 = _denominations[5];
|
||||
}
|
||||
|
||||
function executeProposal() external {
|
||||
TornadoProxy tornadoProxy = TornadoProxy(proxyAddress);
|
||||
|
||||
for (uint256 i = 0; i < 6; i++) {
|
||||
ITornadoInstance instance = ITornadoInstance(instanceFactory.createInstanceClone(denominations(i), token));
|
||||
|
||||
TornadoProxy.Instance memory newInstanceData = TornadoProxy.Instance(
|
||||
true,
|
||||
IERC20(token),
|
||||
TornadoProxy.InstanceState.ENABLED
|
||||
);
|
||||
|
||||
TornadoProxy.Tornado memory tornadoForUpdate = TornadoProxy.Tornado(instance, newInstanceData);
|
||||
|
||||
tornadoProxy.updateInstance(tornadoForUpdate);
|
||||
|
||||
emit UpdatedInstanceForProxy(address(instance), instance.token(), instance.denomination());
|
||||
}
|
||||
}
|
||||
|
||||
function denominations(uint256 index) private view returns (uint256) {
|
||||
if (index > 4) {
|
||||
return denomination6;
|
||||
} else if (index > 3) {
|
||||
return denomination5;
|
||||
} else if (index > 2) {
|
||||
return denomination4;
|
||||
} else if (index > 1) {
|
||||
return denomination3;
|
||||
} else if (index > 0) {
|
||||
return denomination2;
|
||||
} else {
|
||||
return denomination1;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,9 +3,9 @@
|
||||
pragma solidity ^0.7.6;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
|
||||
import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol";
|
||||
import "openzeppelin-solidity/contracts/math/Math.sol";
|
||||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
|
||||
import "@openzeppelin/contracts/math/Math.sol";
|
||||
import "./ITornadoInstance.sol";
|
||||
import "./ITornadoTrees.sol";
|
||||
|
||||
|
@ -6,7 +6,7 @@ require('hardhat-log-remover')
|
||||
require('solidity-coverage')
|
||||
|
||||
require('./tasks/deploy_proposal.js')
|
||||
require('./tasks/deploy_factory.js')
|
||||
require('./tasks/deploy_factory_proposal.js')
|
||||
require('./tasks/propose_proposal.js')
|
||||
/**
|
||||
* @type import('hardhat/config').HardhatUserConfig
|
||||
@ -38,7 +38,7 @@ module.exports = {
|
||||
hardhat: {
|
||||
forking: {
|
||||
url: `https://mainnet.infura.io/v3/${process.env.mainnet_rpc_key}`,
|
||||
blockNumber: 13017436,
|
||||
blockNumber: process.env.use_latest_block == 'true' ? undefined : 13017436,
|
||||
},
|
||||
loggingEnabled: false,
|
||||
},
|
||||
|
@ -9,10 +9,10 @@
|
||||
"prettier:check": "prettier --check . --config .prettierrc",
|
||||
"prettier:fix": "prettier --write . --config .prettierrc",
|
||||
"lint": "yarn eslint && yarn prettier:check",
|
||||
"deploy:factory": "yarn hardhat --network mainnet deploy_factory",
|
||||
"deploy:proposal": "yarn hardhat --network mainnet deploy_proposal --factory-address",
|
||||
"deploy:factory:test": "yarn hardhat --network goerli deploy_factory",
|
||||
"deploy:proposal:test": "yarn hardhat --network goerli deploy_proposal --factory-address",
|
||||
"deploy:proposal:factory": "yarn hardhat --network mainnet deploy_factory_proposal",
|
||||
"deploy:proposal:factory:test": "yarn hardhat --network goerli deploy_factory_proposal",
|
||||
"propose": "yarn hardhat --network mainnet propose_proposal --proposal-address",
|
||||
"test": "yarn hardhat test",
|
||||
"f:test": "yarn test && yarn clean",
|
||||
@ -41,11 +41,11 @@
|
||||
"websnark": "^0.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@openzeppelin/contracts": "3.2.0",
|
||||
"@openzeppelin/contracts": "3.4.2",
|
||||
"@openzeppelin/upgrades-core": "^1.0.1",
|
||||
"openzeppelin-solidity": "https://github.com/OpenZeppelin/openzeppelin-contracts.git#v3.4.0-solc-0.7",
|
||||
"torn-token": "^1.0.4",
|
||||
"tornado-cli": "^0.0.1",
|
||||
"tornado-core": "https://github.com/tornadocash/tornado-core.git",
|
||||
"tornado-governance": "^1.0.2"
|
||||
}
|
||||
}
|
||||
|
@ -2,28 +2,24 @@ module.exports = [
|
||||
{
|
||||
tokenAddress: '0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919',
|
||||
denomination: '33333333333333333333',
|
||||
domain: 'rai-33.tornadocash.eth',
|
||||
symbol: 'RAI',
|
||||
decimals: 18,
|
||||
},
|
||||
{
|
||||
tokenAddress: '0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919',
|
||||
denomination: '333333333333333333333',
|
||||
domain: 'rai-333.tornadocash.eth',
|
||||
symbol: 'RAI',
|
||||
decimals: 18,
|
||||
},
|
||||
{
|
||||
tokenAddress: '0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919',
|
||||
denomination: '3333333333333333333333',
|
||||
domain: 'rai-3333.tornadocash.eth',
|
||||
symbol: 'RAI',
|
||||
decimals: 18,
|
||||
},
|
||||
{
|
||||
tokenAddress: '0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919',
|
||||
denomination: '33333333333333333333333',
|
||||
domain: 'rai-33333.tornadocash.eth',
|
||||
symbol: 'RAI',
|
||||
decimals: 18,
|
||||
},
|
||||
|
@ -1,26 +0,0 @@
|
||||
require('dotenv').config()
|
||||
const { task } = require('hardhat/config')
|
||||
const { BigNumber } = require('@ethersproject/bignumber')
|
||||
|
||||
task('deploy_factory', 'deploy the instance factory').setAction(async (taskArgs, hre) => {
|
||||
const GovernanceAddress = '0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce'
|
||||
const Verifier = `${process.env.VERIFIER}`
|
||||
const Hasher = `${process.env.HASHER}`
|
||||
|
||||
const TornadoInstanceFactoryFactory = await hre.ethers.getContractFactory('TornadoInstanceCloneFactory')
|
||||
const TornadoInstanceFactoryContract = await TornadoInstanceFactoryFactory.deploy(
|
||||
Verifier,
|
||||
Hasher,
|
||||
BigNumber.from(20),
|
||||
)
|
||||
|
||||
await TornadoInstanceFactoryContract.transferOwnership(GovernanceAddress)
|
||||
await TornadoInstanceFactoryContract.deployTransaction.wait(5)
|
||||
|
||||
await hre.run('verify:verify', {
|
||||
address: TornadoInstanceFactoryContract.address,
|
||||
constructorArguments: [Verifier, Hasher, BigNumber.from(20)],
|
||||
})
|
||||
|
||||
console.log('Verified TornadoInstanceFactory deployed at: ', TornadoInstanceFactoryContract.address)
|
||||
})
|
27
tasks/deploy_factory_proposal.js
Normal file
27
tasks/deploy_factory_proposal.js
Normal file
@ -0,0 +1,27 @@
|
||||
require('dotenv').config()
|
||||
const { task } = require('hardhat/config')
|
||||
const { BigNumber } = require('@ethersproject/bignumber')
|
||||
const instancesData = require('../resources/instances')
|
||||
|
||||
task('deploy_factory_proposal', 'deploy the proposal that creates the factory').setAction(
|
||||
async (taskArgs, hre) => {
|
||||
const ProposalFactory = await hre.ethers.getContractFactory('CreateFactoryAndAddInstancesProposal')
|
||||
|
||||
let denominations = []
|
||||
for (let i = 0; i < 4; i++) {
|
||||
denominations[i] = BigNumber.from(instancesData[i].denomination)
|
||||
}
|
||||
const tokenAddress = instancesData[0].tokenAddress
|
||||
|
||||
const ProposalContract = await ProposalFactory.deploy(`${process.env.PROXY}`, denominations, tokenAddress)
|
||||
|
||||
await ProposalContract.deployTransaction.wait(5)
|
||||
|
||||
await hre.run('verify:verify', {
|
||||
address: ProposalContract.address,
|
||||
constructorArguments: [`${process.env.PROXY}`, denominations, tokenAddress],
|
||||
})
|
||||
|
||||
console.log('Verified CreateFactoryAndAddInstancesProposal deployed at: ', ProposalContract.address)
|
||||
},
|
||||
)
|
@ -3,23 +3,38 @@ const { task } = require('hardhat/config')
|
||||
const { BigNumber } = require('@ethersproject/bignumber')
|
||||
const instancesData = require('../resources/instances')
|
||||
|
||||
task('deploy_proposal', 'deploy proposal that uses factory').setAction(async (taskArgs, hre) => {
|
||||
const ProposalFactory = await hre.ethers.getContractFactory('CreateFactoryAndAddInstancesProposal')
|
||||
task('deploy_proposal', 'deploy proposal that uses factory')
|
||||
.addParam('factoryAddress', 'address of factory')
|
||||
.setAction(async (taskArgs, hre) => {
|
||||
const contractName = `Add${instancesData.length}Instance${instancesData.length == 1 ? '' : 's'}`
|
||||
|
||||
let denominations = []
|
||||
for (let i = 0; i < 4; i++) {
|
||||
denominations[i] = BigNumber.from(instancesData[i].denomination)
|
||||
}
|
||||
const tokenAddress = instancesData[0].tokenAddress
|
||||
const ProposalFactory = await hre.ethers.getContractFactory(contractName)
|
||||
|
||||
const ProposalContract = await ProposalFactory.deploy(denominations, tokenAddress)
|
||||
let denominations = []
|
||||
for (let i = 0; i < instancesData.length; i++) {
|
||||
denominations[i] = BigNumber.from(instancesData[i].denomination)
|
||||
}
|
||||
|
||||
await ProposalContract.deployTransaction.wait(5)
|
||||
const tokenAddress = instancesData[0].tokenAddress
|
||||
|
||||
await hre.run('verify:verify', {
|
||||
address: ProposalContract.address,
|
||||
constructorArguments: [denominations, tokenAddress],
|
||||
const ProposalContract = await ProposalFactory.deploy(
|
||||
`${process.env.PROXY}`,
|
||||
taskArgs.factoryAddress,
|
||||
denominations.length == 1 ? denominations[0] : denominations,
|
||||
tokenAddress,
|
||||
)
|
||||
|
||||
await ProposalContract.deployTransaction.wait(5)
|
||||
|
||||
await hre.run('verify:verify', {
|
||||
address: ProposalContract.address,
|
||||
constructorArguments: [
|
||||
`${process.env.PROXY}`,
|
||||
taskArgs.factoryAddress,
|
||||
denominations.length == 1 ? denominations[0] : denominations,
|
||||
tokenAddress,
|
||||
],
|
||||
})
|
||||
|
||||
console.log(`Verified ${contractName} deployed at: `, ProposalContract.address)
|
||||
})
|
||||
|
||||
console.log('Verified CreateFactoryAndAddInstancesProposal deployed at: ', ProposalContract.address)
|
||||
})
|
||||
|
@ -142,7 +142,7 @@ describe('Deployments test setup', () => {
|
||||
.toNumber(),
|
||||
)
|
||||
const overrides = {
|
||||
gasLimit: BigNumber.from('6000000'),
|
||||
gasLimit: BigNumber.from('30000000'),
|
||||
}
|
||||
await GovernanceContract.execute(id, overrides)
|
||||
})
|
||||
@ -233,9 +233,9 @@ describe('Deployments test setup', () => {
|
||||
TornadoProxy = await TornadoProxy.connect(whaleRAI)
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
instanceAddresses[i] = await TornadoInstanceFactoryContract.instanceClones(
|
||||
RAIToken.address,
|
||||
instanceAddresses[i] = await TornadoInstanceFactoryContract.getInstanceAddress(
|
||||
denominations[i],
|
||||
RAIToken.address,
|
||||
)
|
||||
}
|
||||
|
||||
@ -332,4 +332,15 @@ describe('Deployments test setup', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await ethers.provider.send('hardhat_reset', [
|
||||
{
|
||||
forking: {
|
||||
jsonRpcUrl: `https://mainnet.infura.io/v3/${process.env.mainnet_rpc_key}`,
|
||||
blockNumber: process.env.use_latest_block == 'true' ? undefined : 13017436,
|
||||
},
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
@ -68,7 +68,7 @@ describe('Deployments test setup', () => {
|
||||
|
||||
before(async () => {
|
||||
accounts = await ethers.getSigners()
|
||||
ProposalFactory = await ethers.getContractFactory('AddWithFactoryProposal')
|
||||
ProposalFactory = await ethers.getContractFactory('Add4Instances')
|
||||
GovernanceContract = await ethers.getContractAt(
|
||||
'Governance',
|
||||
'0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce',
|
||||
@ -214,7 +214,7 @@ describe('Deployments test setup', () => {
|
||||
.toNumber(),
|
||||
)
|
||||
const overrides = {
|
||||
gasLimit: BigNumber.from('6000000'),
|
||||
gasLimit: BigNumber.from('30000000'),
|
||||
}
|
||||
await GovernanceContract.execute(id, overrides)
|
||||
})
|
||||
@ -242,9 +242,9 @@ describe('Deployments test setup', () => {
|
||||
TornadoProxy = await TornadoProxy.connect(whaleRAI)
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
instanceAddresses[i] = await TornadoInstanceFactoryContract.instanceClones(
|
||||
RAIToken.address,
|
||||
instanceAddresses[i] = await TornadoInstanceFactoryContract.getInstanceAddress(
|
||||
denominations[i],
|
||||
RAIToken.address,
|
||||
)
|
||||
}
|
||||
|
||||
@ -341,4 +341,15 @@ describe('Deployments test setup', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await ethers.provider.send('hardhat_reset', [
|
||||
{
|
||||
forking: {
|
||||
jsonRpcUrl: `https://mainnet.infura.io/v3/${process.env.mainnet_rpc_key}`,
|
||||
blockNumber: process.env.use_latest_block == 'true' ? undefined : 13017436,
|
||||
},
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue
Block a user