mirror of
https://github.com/tornadocash/tornado-pool-factory
synced 2024-02-02 15:04:08 +01:00
contracts compile successfully
This commit is contained in:
parent
bffcaeacb9
commit
35004bc184
89
contracts/AddInstanceProposal.sol
Normal file
89
contracts/AddInstanceProposal.sol
Normal file
@ -0,0 +1,89 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity 0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import "./interfaces/IInstanceRegistry.sol";
|
||||
import "./InstanceFactory.sol";
|
||||
|
||||
contract AddInstanceProposal {
|
||||
InstanceFactory public immutable instanceFactory;
|
||||
IInstanceRegistry public immutable instanceRegistry;
|
||||
address public immutable token;
|
||||
uint24 public immutable uniswapPoolSwappingFee;
|
||||
|
||||
uint256 internal immutable numInstances;
|
||||
uint256 internal immutable denomination0;
|
||||
uint256 internal immutable denomination1;
|
||||
uint256 internal immutable denomination2;
|
||||
uint32 internal immutable protocolFee0;
|
||||
uint32 internal immutable protocolFee1;
|
||||
uint32 internal immutable protocolFee2;
|
||||
|
||||
event AddInstanceForRegistry(address instance, address token, uint256 denomination);
|
||||
|
||||
constructor(
|
||||
address _instanceFactory,
|
||||
address _instanceRegistry,
|
||||
address _token,
|
||||
uint24 _uniswapPoolSwappingFee,
|
||||
uint256[] memory _denominations,
|
||||
uint32[] memory _protocolFees
|
||||
) {
|
||||
instanceFactory = InstanceFactory(_instanceFactory);
|
||||
instanceRegistry = IInstanceRegistry(_instanceRegistry);
|
||||
token = _token;
|
||||
uniswapPoolSwappingFee = _uniswapPoolSwappingFee;
|
||||
|
||||
require(_denominations.length == _protocolFees.length);
|
||||
uint256 _numInstances = _denominations.length;
|
||||
require(_numInstances > 0);
|
||||
require(_numInstances < 4);
|
||||
numInstances = _numInstances;
|
||||
|
||||
denomination0 = _numInstances > 0 ? _denominations[0] : 0;
|
||||
denomination1 = _numInstances > 1 ? _denominations[1] : 0;
|
||||
denomination2 = _numInstances > 2 ? _denominations[2] : 0;
|
||||
protocolFee0 = _numInstances > 0 ? _protocolFees[0] : 0;
|
||||
protocolFee1 = _numInstances > 1 ? _protocolFees[1] : 0;
|
||||
protocolFee2 = _numInstances > 2 ? _protocolFees[2] : 0;
|
||||
}
|
||||
|
||||
function executeProposal() external {
|
||||
for (uint256 i = 0; i < numInstances; i++) {
|
||||
address instance = instanceFactory.createInstanceClone(denominationByIndex(i), token);
|
||||
|
||||
IInstanceRegistry.Instance memory newInstanceData = IInstanceRegistry.Instance(
|
||||
true,
|
||||
IERC20(token),
|
||||
IInstanceRegistry.InstanceState.ENABLED,
|
||||
uniswapPoolSwappingFee,
|
||||
protocolFeeByIndex(i)
|
||||
);
|
||||
|
||||
IInstanceRegistry.Tornado memory tornadoForUpdate = IInstanceRegistry.Tornado(instance, newInstanceData);
|
||||
|
||||
instanceRegistry.updateInstance(tornadoForUpdate);
|
||||
|
||||
emit AddInstanceForRegistry(address(instance), token, denominationByIndex(i));
|
||||
}
|
||||
}
|
||||
|
||||
function denominationByIndex(uint256 _index) public view returns (uint256) {
|
||||
if (_index == 0) { return denomination0; }
|
||||
else if (_index == 1) { return denomination1; }
|
||||
else if (_index == 2) { return denomination2; }
|
||||
else {
|
||||
revert("Invalid instance index");
|
||||
}
|
||||
}
|
||||
|
||||
function protocolFeeByIndex(uint256 _index) public view returns (uint32) {
|
||||
if (_index == 0) { return protocolFee0; }
|
||||
else if (_index == 1) { return protocolFee1; }
|
||||
else if (_index == 2) { return protocolFee2; }
|
||||
else {
|
||||
revert("Invalid instance index");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import "./TornadoInstanceCloneFactory.sol";
|
||||
import "./tornado_proxy/TornadoProxy.sol";
|
||||
|
||||
contract CreateFactoryAndAddInstancesProposal {
|
||||
address public constant verifier = 0xce172ce1F20EC0B3728c9965470eaf994A03557A;
|
||||
address public constant hasher = 0x83584f83f26aF4eDDA9CBe8C730bc87C364b28fe;
|
||||
address public constant governance = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce;
|
||||
|
||||
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;
|
||||
|
||||
event UpdatedInstanceForProxy(address indexed instance, address indexed token, uint256 indexed denomination);
|
||||
|
||||
constructor(
|
||||
address _proxyAddress,
|
||||
uint256[4] memory _denominations,
|
||||
address _token
|
||||
) {
|
||||
TornadoInstanceCloneFactory cachedFactory = new TornadoInstanceCloneFactory(verifier, hasher, 20);
|
||||
cachedFactory.transferOwnership(governance);
|
||||
instanceFactory = cachedFactory;
|
||||
|
||||
token = _token;
|
||||
proxyAddress = _proxyAddress;
|
||||
|
||||
denomination1 = _denominations[0];
|
||||
denomination2 = _denominations[1];
|
||||
denomination3 = _denominations[2];
|
||||
denomination4 = _denominations[3];
|
||||
}
|
||||
|
||||
function executeProposal() external {
|
||||
TornadoProxy tornadoProxy = TornadoProxy(proxyAddress);
|
||||
|
||||
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);
|
||||
|
||||
emit UpdatedInstanceForProxy(address(instance), instance.token(), instance.denomination());
|
||||
}
|
||||
}
|
||||
|
||||
function denominations(uint256 index) private view returns (uint256) {
|
||||
if (index > 2) {
|
||||
return denomination4;
|
||||
} else if (index > 1) {
|
||||
return denomination3;
|
||||
} else if (index > 0) {
|
||||
return denomination2;
|
||||
} else {
|
||||
return denomination1;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
|
||||
pragma solidity 0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import "tornado-core/contracts/ERC20Tornado.sol";
|
||||
@ -13,12 +14,10 @@ contract ERC20TornadoCloneable is ERC20Tornado {
|
||||
address _token
|
||||
) external {
|
||||
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");
|
||||
denomination = _denomination;
|
||||
/// In Constructor: MerkleTreeWithHistory
|
||||
require(_merkleTreeHeight > 0, "_levels should be greater than zero");
|
||||
require(_merkleTreeHeight < 32, "_levels should be less than 32");
|
||||
levels = _merkleTreeHeight;
|
||||
|
@ -1,337 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
// https://tornado.cash
|
||||
/*
|
||||
* d888888P dP a88888b. dP
|
||||
* 88 88 d8' `88 88
|
||||
* 88 .d8888b. 88d888b. 88d888b. .d8888b. .d888b88 .d8888b. 88 .d8888b. .d8888b. 88d888b.
|
||||
* 88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88 88' `88 Y8ooooo. 88' `88
|
||||
* 88 88. .88 88 88 88 88. .88 88. .88 88. .88 dP Y8. .88 88. .88 88 88 88
|
||||
* dP `88888P' dP dP dP `88888P8 `88888P8 `88888P' 88 Y88888P' `88888P8 `88888P' dP dP
|
||||
* ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
|
||||
*/
|
||||
|
||||
interface IHasher {
|
||||
function MiMCSponge(uint256 in_xL, uint256 in_xR) external pure returns (uint256 xL, uint256 xR);
|
||||
}
|
||||
|
||||
contract MerkleTreeWithHistory {
|
||||
uint256 public constant FIELD_SIZE = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||
uint256 public constant ZERO_VALUE = 21663839004416932945382355908790599225266501822907911457504978515578255421292; // = keccak256("tornado") % FIELD_SIZE
|
||||
|
||||
IHasher public hasher;
|
||||
uint32 public levels;
|
||||
|
||||
// the following variables are made public for easier testing and debugging and
|
||||
// are not supposed to be accessed in regular code
|
||||
|
||||
// filledSubtrees and roots could be bytes32[size], but using mappings makes it cheaper because
|
||||
// it removes index range check on every interaction
|
||||
mapping(uint256 => bytes32) public filledSubtrees;
|
||||
mapping(uint256 => bytes32) public roots;
|
||||
uint32 public constant ROOT_HISTORY_SIZE = 30;
|
||||
uint32 public currentRootIndex = 0;
|
||||
uint32 public nextIndex = 0;
|
||||
|
||||
constructor(uint32 _levels, IHasher _hasher) {
|
||||
require(_levels > 0, "_levels should be greater than zero");
|
||||
require(_levels < 32, "_levels should be less than 32");
|
||||
levels = _levels;
|
||||
hasher = _hasher;
|
||||
|
||||
for (uint32 i = 0; i < _levels; i++) {
|
||||
filledSubtrees[i] = zeros(i);
|
||||
}
|
||||
|
||||
roots[0] = zeros(_levels - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@dev Hash 2 tree leaves, returns MiMC(_left, _right)
|
||||
*/
|
||||
function hashLeftRight(
|
||||
IHasher _hasher,
|
||||
bytes32 _left,
|
||||
bytes32 _right
|
||||
) public pure returns (bytes32) {
|
||||
require(uint256(_left) < FIELD_SIZE, "_left should be inside the field");
|
||||
require(uint256(_right) < FIELD_SIZE, "_right should be inside the field");
|
||||
uint256 R = uint256(_left);
|
||||
uint256 C = 0;
|
||||
(R, C) = _hasher.MiMCSponge(R, C);
|
||||
R = addmod(R, uint256(_right), FIELD_SIZE);
|
||||
(R, C) = _hasher.MiMCSponge(R, C);
|
||||
return bytes32(R);
|
||||
}
|
||||
|
||||
function _insert(bytes32 _leaf) internal returns (uint32 index) {
|
||||
uint32 _nextIndex = nextIndex;
|
||||
require(_nextIndex != uint32(2)**levels, "Merkle tree is full. No more leaves can be added");
|
||||
uint32 currentIndex = _nextIndex;
|
||||
bytes32 currentLevelHash = _leaf;
|
||||
bytes32 left;
|
||||
bytes32 right;
|
||||
|
||||
for (uint32 i = 0; i < levels; i++) {
|
||||
if (currentIndex % 2 == 0) {
|
||||
left = currentLevelHash;
|
||||
right = zeros(i);
|
||||
filledSubtrees[i] = currentLevelHash;
|
||||
} else {
|
||||
left = filledSubtrees[i];
|
||||
right = currentLevelHash;
|
||||
}
|
||||
currentLevelHash = hashLeftRight(hasher, left, right);
|
||||
currentIndex /= 2;
|
||||
}
|
||||
|
||||
uint32 newRootIndex = (currentRootIndex + 1) % ROOT_HISTORY_SIZE;
|
||||
currentRootIndex = newRootIndex;
|
||||
roots[newRootIndex] = currentLevelHash;
|
||||
nextIndex = _nextIndex + 1;
|
||||
return _nextIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
@dev Whether the root is present in the root history
|
||||
*/
|
||||
function isKnownRoot(bytes32 _root) public view returns (bool) {
|
||||
if (_root == 0) {
|
||||
return false;
|
||||
}
|
||||
uint32 _currentRootIndex = currentRootIndex;
|
||||
uint32 i = _currentRootIndex;
|
||||
do {
|
||||
if (_root == roots[i]) {
|
||||
return true;
|
||||
}
|
||||
if (i == 0) {
|
||||
i = ROOT_HISTORY_SIZE;
|
||||
}
|
||||
i--;
|
||||
} while (i != _currentRootIndex);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@dev Returns the last root
|
||||
*/
|
||||
function getLastRoot() public view returns (bytes32) {
|
||||
return roots[currentRootIndex];
|
||||
}
|
||||
|
||||
/// @dev provides Zero (Empty) elements for a MiMC MerkleTree. Up to 32 levels
|
||||
function zeros(uint256 i) public pure returns (bytes32) {
|
||||
if (i == 0) return bytes32(0x2fe54c60d3acabf3343a35b6eba15db4821b340f76e741e2249685ed4899af6c);
|
||||
else if (i == 1) return bytes32(0x256a6135777eee2fd26f54b8b7037a25439d5235caee224154186d2b8a52e31d);
|
||||
else if (i == 2) return bytes32(0x1151949895e82ab19924de92c40a3d6f7bcb60d92b00504b8199613683f0c200);
|
||||
else if (i == 3) return bytes32(0x20121ee811489ff8d61f09fb89e313f14959a0f28bb428a20dba6b0b068b3bdb);
|
||||
else if (i == 4) return bytes32(0x0a89ca6ffa14cc462cfedb842c30ed221a50a3d6bf022a6a57dc82ab24c157c9);
|
||||
else if (i == 5) return bytes32(0x24ca05c2b5cd42e890d6be94c68d0689f4f21c9cec9c0f13fe41d566dfb54959);
|
||||
else if (i == 6) return bytes32(0x1ccb97c932565a92c60156bdba2d08f3bf1377464e025cee765679e604a7315c);
|
||||
else if (i == 7) return bytes32(0x19156fbd7d1a8bf5cba8909367de1b624534ebab4f0f79e003bccdd1b182bdb4);
|
||||
else if (i == 8) return bytes32(0x261af8c1f0912e465744641409f622d466c3920ac6e5ff37e36604cb11dfff80);
|
||||
else if (i == 9) return bytes32(0x0058459724ff6ca5a1652fcbc3e82b93895cf08e975b19beab3f54c217d1c007);
|
||||
else if (i == 10) return bytes32(0x1f04ef20dee48d39984d8eabe768a70eafa6310ad20849d4573c3c40c2ad1e30);
|
||||
else if (i == 11) return bytes32(0x1bea3dec5dab51567ce7e200a30f7ba6d4276aeaa53e2686f962a46c66d511e5);
|
||||
else if (i == 12) return bytes32(0x0ee0f941e2da4b9e31c3ca97a40d8fa9ce68d97c084177071b3cb46cd3372f0f);
|
||||
else if (i == 13) return bytes32(0x1ca9503e8935884501bbaf20be14eb4c46b89772c97b96e3b2ebf3a36a948bbd);
|
||||
else if (i == 14) return bytes32(0x133a80e30697cd55d8f7d4b0965b7be24057ba5dc3da898ee2187232446cb108);
|
||||
else if (i == 15) return bytes32(0x13e6d8fc88839ed76e182c2a779af5b2c0da9dd18c90427a644f7e148a6253b6);
|
||||
else if (i == 16) return bytes32(0x1eb16b057a477f4bc8f572ea6bee39561098f78f15bfb3699dcbb7bd8db61854);
|
||||
else if (i == 17) return bytes32(0x0da2cb16a1ceaabf1c16b838f7a9e3f2a3a3088d9e0a6debaa748114620696ea);
|
||||
else if (i == 18) return bytes32(0x24a3b3d822420b14b5d8cb6c28a574f01e98ea9e940551d2ebd75cee12649f9d);
|
||||
else if (i == 19) return bytes32(0x198622acbd783d1b0d9064105b1fc8e4d8889de95c4c519b3f635809fe6afc05);
|
||||
else if (i == 20) return bytes32(0x29d7ed391256ccc3ea596c86e933b89ff339d25ea8ddced975ae2fe30b5296d4);
|
||||
else if (i == 21) return bytes32(0x19be59f2f0413ce78c0c3703a3a5451b1d7f39629fa33abd11548a76065b2967);
|
||||
else if (i == 22) return bytes32(0x1ff3f61797e538b70e619310d33f2a063e7eb59104e112e95738da1254dc3453);
|
||||
else if (i == 23) return bytes32(0x10c16ae9959cf8358980d9dd9616e48228737310a10e2b6b731c1a548f036c48);
|
||||
else if (i == 24) return bytes32(0x0ba433a63174a90ac20992e75e3095496812b652685b5e1a2eae0b1bf4e8fcd1);
|
||||
else if (i == 25) return bytes32(0x019ddb9df2bc98d987d0dfeca9d2b643deafab8f7036562e627c3667266a044c);
|
||||
else if (i == 26) return bytes32(0x2d3c88b23175c5a5565db928414c66d1912b11acf974b2e644caaac04739ce99);
|
||||
else if (i == 27) return bytes32(0x2eab55f6ae4e66e32c5189eed5c470840863445760f5ed7e7b69b2a62600f354);
|
||||
else if (i == 28) return bytes32(0x002df37a2642621802383cf952bf4dd1f32e05433beeb1fd41031fb7eace979d);
|
||||
else if (i == 29) return bytes32(0x104aeb41435db66c3e62feccc1d6f5d98d0a0ed75d1374db457cf462e3a1f427);
|
||||
else if (i == 30) return bytes32(0x1f3c6fd858e9a7d4b0d1f38e256a09d81d5a5e3c963987e2d4b814cfab7c6ebb);
|
||||
else if (i == 31) return bytes32(0x2c7a07d20dff79d01fecedc1134284a8d08436606c93693b67e333f671bf69cc);
|
||||
else revert("Index out of bounds");
|
||||
}
|
||||
}
|
||||
|
||||
// https://tornado.cash
|
||||
/*
|
||||
* d888888P dP a88888b. dP
|
||||
* 88 88 d8' `88 88
|
||||
* 88 .d8888b. 88d888b. 88d888b. .d8888b. .d888b88 .d8888b. 88 .d8888b. .d8888b. 88d888b.
|
||||
* 88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88 88' `88 Y8ooooo. 88' `88
|
||||
* 88 88. .88 88 88 88 88. .88 88. .88 88. .88 dP Y8. .88 88. .88 88 88 88
|
||||
* dP `88888P' dP dP dP `88888P8 `88888P8 `88888P' 88 Y88888P' `88888P8 `88888P' dP dP
|
||||
* ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
|
||||
*/
|
||||
|
||||
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
||||
|
||||
interface IVerifier {
|
||||
function verifyProof(bytes memory _proof, uint256[6] memory _input) external returns (bool);
|
||||
}
|
||||
|
||||
abstract contract Tornado is MerkleTreeWithHistory, ReentrancyGuard {
|
||||
IVerifier public verifier;
|
||||
uint256 public denomination;
|
||||
|
||||
mapping(bytes32 => bool) public nullifierHashes;
|
||||
// we store all commitments just to prevent accidental deposits with the same commitment
|
||||
mapping(bytes32 => bool) public commitments;
|
||||
|
||||
event Deposit(bytes32 indexed commitment, uint32 leafIndex, uint256 timestamp);
|
||||
event Withdrawal(address to, bytes32 nullifierHash, address indexed relayer, uint256 fee);
|
||||
|
||||
/**
|
||||
@dev The constructor
|
||||
@param _verifier the address of SNARK verifier for this contract
|
||||
@param _hasher the address of MiMC hash contract
|
||||
@param _denomination transfer amount for each deposit
|
||||
@param _merkleTreeHeight the height of deposits' Merkle Tree
|
||||
*/
|
||||
constructor(
|
||||
IVerifier _verifier,
|
||||
IHasher _hasher,
|
||||
uint256 _denomination,
|
||||
uint32 _merkleTreeHeight
|
||||
) MerkleTreeWithHistory(_merkleTreeHeight, _hasher) {
|
||||
require(_denomination > 0, "denomination should be greater than 0");
|
||||
verifier = _verifier;
|
||||
denomination = _denomination;
|
||||
}
|
||||
|
||||
/**
|
||||
@dev Deposit funds into the contract. The caller must send (for ETH) or approve (for ERC20) value equal to or `denomination` of this instance.
|
||||
@param _commitment the note commitment, which is PedersenHash(nullifier + secret)
|
||||
*/
|
||||
function deposit(bytes32 _commitment) external payable nonReentrant {
|
||||
require(!commitments[_commitment], "The commitment has been submitted");
|
||||
|
||||
uint32 insertedIndex = _insert(_commitment);
|
||||
commitments[_commitment] = true;
|
||||
_processDeposit();
|
||||
|
||||
emit Deposit(_commitment, insertedIndex, block.timestamp);
|
||||
}
|
||||
|
||||
/** @dev this function is defined in a child contract */
|
||||
function _processDeposit() internal virtual;
|
||||
|
||||
/**
|
||||
@dev Withdraw a deposit from the contract. `proof` is a zkSNARK proof data, and input is an array of circuit public inputs
|
||||
`input` array consists of:
|
||||
- merkle root of all deposits in the contract
|
||||
- hash of unique deposit nullifier to prevent double spends
|
||||
- the recipient of funds
|
||||
- optional fee that goes to the transaction sender (usually a relay)
|
||||
*/
|
||||
function withdraw(
|
||||
bytes calldata _proof,
|
||||
bytes32 _root,
|
||||
bytes32 _nullifierHash,
|
||||
address payable _recipient,
|
||||
address payable _relayer,
|
||||
uint256 _fee,
|
||||
uint256 _refund
|
||||
) external payable nonReentrant {
|
||||
require(_fee <= denomination, "Fee exceeds transfer value");
|
||||
require(!nullifierHashes[_nullifierHash], "The note has been already spent");
|
||||
require(isKnownRoot(_root), "Cannot find your merkle root"); // Make sure to use a recent one
|
||||
require(
|
||||
verifier.verifyProof(
|
||||
_proof,
|
||||
[uint256(_root), uint256(_nullifierHash), uint256(_recipient), uint256(_relayer), _fee, _refund]
|
||||
),
|
||||
"Invalid withdraw proof"
|
||||
);
|
||||
|
||||
nullifierHashes[_nullifierHash] = true;
|
||||
_processWithdraw(_recipient, _relayer, _fee, _refund);
|
||||
emit Withdrawal(_recipient, _nullifierHash, _relayer, _fee);
|
||||
}
|
||||
|
||||
/** @dev this function is defined in a child contract */
|
||||
function _processWithdraw(
|
||||
address payable _recipient,
|
||||
address payable _relayer,
|
||||
uint256 _fee,
|
||||
uint256 _refund
|
||||
) internal virtual;
|
||||
|
||||
/** @dev whether a note is already spent */
|
||||
function isSpent(bytes32 _nullifierHash) public view returns (bool) {
|
||||
return nullifierHashes[_nullifierHash];
|
||||
}
|
||||
|
||||
/** @dev whether an array of notes is already spent */
|
||||
function isSpentArray(bytes32[] calldata _nullifierHashes) external view returns (bool[] memory spent) {
|
||||
spent = new bool[](_nullifierHashes.length);
|
||||
for (uint256 i = 0; i < _nullifierHashes.length; i++) {
|
||||
if (isSpent(_nullifierHashes[i])) {
|
||||
spent[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://tornado.cash
|
||||
/*
|
||||
* d888888P dP a88888b. dP
|
||||
* 88 88 d8' `88 88
|
||||
* 88 .d8888b. 88d888b. 88d888b. .d8888b. .d888b88 .d8888b. 88 .d8888b. .d8888b. 88d888b.
|
||||
* 88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88 88' `88 Y8ooooo. 88' `88
|
||||
* 88 88. .88 88 88 88 88. .88 88. .88 88. .88 dP Y8. .88 88. .88 88 88 88
|
||||
* dP `88888P' dP dP dP `88888P8 `88888P8 `88888P' 88 Y88888P' `88888P8 `88888P' dP dP
|
||||
* ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
|
||||
*/
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
|
||||
|
||||
contract ERC20Tornado is Tornado {
|
||||
using SafeERC20 for IERC20;
|
||||
IERC20 public token;
|
||||
|
||||
constructor(
|
||||
IVerifier _verifier,
|
||||
IHasher _hasher,
|
||||
uint256 _denomination,
|
||||
uint32 _merkleTreeHeight,
|
||||
IERC20 _token
|
||||
) Tornado(_verifier, _hasher, _denomination, _merkleTreeHeight) {
|
||||
token = _token;
|
||||
}
|
||||
|
||||
function _processDeposit() internal override {
|
||||
require(msg.value == 0, "ETH value is supposed to be 0 for ERC20 instance");
|
||||
token.safeTransferFrom(msg.sender, address(this), denomination);
|
||||
}
|
||||
|
||||
function _processWithdraw(
|
||||
address payable _recipient,
|
||||
address payable _relayer,
|
||||
uint256 _fee,
|
||||
uint256 _refund
|
||||
) internal override {
|
||||
require(msg.value == _refund, "Incorrect refund amount received by the contract");
|
||||
|
||||
token.safeTransfer(_recipient, denomination - _fee);
|
||||
if (_fee > 0) {
|
||||
token.safeTransfer(_relayer, _fee);
|
||||
}
|
||||
|
||||
if (_refund > 0) {
|
||||
(bool success, ) = _recipient.call{ value: _refund }("");
|
||||
if (!success) {
|
||||
// let's return _refund back to the relayer
|
||||
_relayer.transfer(_refund);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +1,20 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
|
||||
pragma solidity 0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
|
||||
|
||||
import "@openzeppelin/contracts/proxy/Clones.sol";
|
||||
import "./ERC20TornadoCloneable.sol";
|
||||
import "./AddInstanceProposal.sol";
|
||||
import "./interfaces/IGovernance.sol";
|
||||
|
||||
contract TornadoInstanceCloneFactory is Ownable {
|
||||
contract InstanceFactory is Ownable {
|
||||
using Clones for address;
|
||||
using Address for address;
|
||||
|
||||
address immutable governance;
|
||||
address public implementation;
|
||||
address public verifier;
|
||||
address public hasher;
|
||||
@ -26,13 +29,58 @@ contract TornadoInstanceCloneFactory is Ownable {
|
||||
constructor(
|
||||
address _verifier,
|
||||
address _hasher,
|
||||
uint32 _merkleTreeHeight
|
||||
uint32 _merkleTreeHeight,
|
||||
address _governance
|
||||
) {
|
||||
verifier = _verifier;
|
||||
hasher = _hasher;
|
||||
merkleTreeHeight = _merkleTreeHeight;
|
||||
ERC20TornadoCloneable implContract = new ERC20TornadoCloneable(_verifier, _hasher);
|
||||
implementation = address(implContract);
|
||||
governance = _governance;
|
||||
transferOwnership(_governance);
|
||||
}
|
||||
|
||||
function createInstanceClone(uint256 _denomination, address _token) external onlyOwner returns (address) {
|
||||
bytes32 salt = keccak256(abi.encodePacked(_denomination, _token));
|
||||
|
||||
require(!implementation.predictDeterministicAddress(salt).isContract(), "Instance already exists");
|
||||
|
||||
address newClone = implementation.cloneDeterministic(salt);
|
||||
|
||||
emit NewInstanceCloneCreated(newClone);
|
||||
ERC20TornadoCloneable(newClone).init(_denomination, merkleTreeHeight, _token);
|
||||
return newClone;
|
||||
}
|
||||
|
||||
function getInstanceAddress(uint256 _denomination, address _token) public view returns (address) {
|
||||
bytes32 salt = keccak256(abi.encodePacked(_denomination, _token));
|
||||
return implementation.predictDeterministicAddress(salt);
|
||||
}
|
||||
|
||||
function createNewProposal(
|
||||
string calldata _description,
|
||||
address _instanceRegistry,
|
||||
address _token,
|
||||
uint24 _uniswapPoolSwappingFee,
|
||||
uint256[] memory _denominations,
|
||||
uint32[] memory _protocolFees
|
||||
) external returns (address) {
|
||||
// TODO test params
|
||||
require(_denominations.length == _protocolFees.length);
|
||||
|
||||
address proposal = address(new AddInstanceProposal(
|
||||
address(this),
|
||||
_instanceRegistry,
|
||||
_token,
|
||||
_uniswapPoolSwappingFee,
|
||||
_denominations,
|
||||
_protocolFees
|
||||
));
|
||||
|
||||
IGovernance(governance).propose(proposal, _description);
|
||||
|
||||
return proposal;
|
||||
}
|
||||
|
||||
function setVerifier(address _verifier) external onlyOwner {
|
||||
@ -58,21 +106,4 @@ contract TornadoInstanceCloneFactory is Ownable {
|
||||
function generateNewImplementation() external onlyOwner {
|
||||
implementation = address(new ERC20TornadoCloneable(verifier, hasher));
|
||||
}
|
||||
|
||||
function createInstanceClone(uint256 _denomination, address _token) external onlyOwner returns (address) {
|
||||
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) public view returns (address) {
|
||||
bytes32 salt = keccak256(abi.encodePacked(_denomination, _token));
|
||||
return implementation.predictDeterministicAddress(salt);
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
// 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());
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import "../TornadoInstanceCloneFactory.sol";
|
||||
import "../tornado_proxy/TornadoProxy.sol";
|
||||
|
||||
contract Add4Instances {
|
||||
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;
|
||||
|
||||
event UpdatedInstanceForProxy(address instance, address token, uint256 denomination);
|
||||
|
||||
constructor(
|
||||
address _proxyAddress,
|
||||
address _instanceFactory,
|
||||
uint256[4] memory _denominations,
|
||||
address _token
|
||||
) {
|
||||
instanceFactory = TornadoInstanceCloneFactory(_instanceFactory);
|
||||
token = _token;
|
||||
proxyAddress = _proxyAddress;
|
||||
|
||||
denomination1 = _denominations[0];
|
||||
denomination2 = _denominations[1];
|
||||
denomination3 = _denominations[2];
|
||||
denomination4 = _denominations[3];
|
||||
}
|
||||
|
||||
function executeProposal() external {
|
||||
TornadoProxy tornadoProxy = TornadoProxy(proxyAddress);
|
||||
|
||||
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);
|
||||
|
||||
emit UpdatedInstanceForProxy(address(instance), instance.token(), instance.denomination());
|
||||
}
|
||||
}
|
||||
|
||||
function denominations(uint256 index) private view returns (uint256) {
|
||||
if (index > 2) {
|
||||
return denomination4;
|
||||
} else if (index > 1) {
|
||||
return denomination3;
|
||||
} else if (index > 0) {
|
||||
return denomination2;
|
||||
} else {
|
||||
return denomination1;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
7
contracts/interfaces/IGovernance.sol
Normal file
7
contracts/interfaces/IGovernance.sol
Normal file
@ -0,0 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity 0.7.6;
|
||||
|
||||
interface IGovernance {
|
||||
function propose(address target, string memory description) external returns (uint256);
|
||||
}
|
28
contracts/interfaces/IInstanceRegistry.sol
Normal file
28
contracts/interfaces/IInstanceRegistry.sol
Normal file
@ -0,0 +1,28 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity 0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
||||
interface IInstanceRegistry {
|
||||
|
||||
enum InstanceState { DISABLED, ENABLED}
|
||||
|
||||
struct Instance {
|
||||
bool isERC20;
|
||||
IERC20 token;
|
||||
InstanceState state;
|
||||
// the fee of the uniswap pool which will be used to get a TWAP
|
||||
uint24 uniswapPoolSwappingFee;
|
||||
// the fee the protocol takes from relayer, it should be multiplied by PROTOCOL_FEE_DIVIDER from FeeManager.sol
|
||||
uint32 protocolFeePercentage;
|
||||
}
|
||||
|
||||
struct Tornado {
|
||||
address addr;
|
||||
Instance instance;
|
||||
}
|
||||
|
||||
function updateInstance(Tornado calldata _tornado) external;
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.6.12;
|
||||
|
||||
import { Governance } from "tornado-governance/contracts/Governance.sol";
|
||||
pragma solidity 0.6.12 || 0.7.6;
|
||||
|
||||
import { Governance } from "tornado-governance/contracts/v1/Governance.sol";
|
||||
|
||||
contract CompileDummy {}
|
||||
|
@ -1,21 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.7.6;
|
||||
|
||||
interface ITornadoInstance {
|
||||
function token() external view returns (address);
|
||||
|
||||
function denomination() external view returns (uint256);
|
||||
|
||||
function deposit(bytes32 commitment) external payable;
|
||||
|
||||
function withdraw(
|
||||
bytes calldata proof,
|
||||
bytes32 root,
|
||||
bytes32 nullifierHash,
|
||||
address payable recipient,
|
||||
address payable relayer,
|
||||
uint256 fee,
|
||||
uint256 refund
|
||||
) external payable;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.7.6;
|
||||
|
||||
interface ITornadoTrees {
|
||||
function registerDeposit(address instance, bytes32 commitment) external;
|
||||
|
||||
function registerWithdrawal(address instance, bytes32 nullifier) external;
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.7.6;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
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";
|
||||
|
||||
contract TornadoProxy {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
event EncryptedNote(address indexed sender, bytes encryptedNote);
|
||||
event InstanceStateUpdated(ITornadoInstance indexed instance, InstanceState state);
|
||||
event TornadoTreesUpdated(ITornadoTrees addr);
|
||||
|
||||
enum InstanceState {
|
||||
DISABLED,
|
||||
ENABLED,
|
||||
MINEABLE
|
||||
}
|
||||
|
||||
struct Instance {
|
||||
bool isERC20;
|
||||
IERC20 token;
|
||||
InstanceState state;
|
||||
}
|
||||
|
||||
struct Tornado {
|
||||
ITornadoInstance addr;
|
||||
Instance instance;
|
||||
}
|
||||
|
||||
ITornadoTrees public tornadoTrees;
|
||||
address public immutable governance;
|
||||
mapping(ITornadoInstance => Instance) public instances;
|
||||
|
||||
modifier onlyGovernance() {
|
||||
require(msg.sender == governance, "Not authorized");
|
||||
_;
|
||||
}
|
||||
|
||||
constructor(
|
||||
address _tornadoTrees,
|
||||
address _governance,
|
||||
Tornado[] memory _instances
|
||||
) public {
|
||||
tornadoTrees = ITornadoTrees(_tornadoTrees);
|
||||
governance = _governance;
|
||||
|
||||
for (uint256 i = 0; i < _instances.length; i++) {
|
||||
_updateInstance(_instances[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function deposit(
|
||||
ITornadoInstance _tornado,
|
||||
bytes32 _commitment,
|
||||
bytes calldata _encryptedNote
|
||||
) external payable {
|
||||
Instance memory instance = instances[_tornado];
|
||||
require(instance.state != InstanceState.DISABLED, "The instance is not supported");
|
||||
|
||||
if (instance.isERC20) {
|
||||
instance.token.safeTransferFrom(msg.sender, address(this), _tornado.denomination());
|
||||
}
|
||||
_tornado.deposit{ value: msg.value }(_commitment);
|
||||
|
||||
if (instance.state == InstanceState.MINEABLE) {
|
||||
tornadoTrees.registerDeposit(address(_tornado), _commitment);
|
||||
}
|
||||
emit EncryptedNote(msg.sender, _encryptedNote);
|
||||
}
|
||||
|
||||
function withdraw(
|
||||
ITornadoInstance _tornado,
|
||||
bytes calldata _proof,
|
||||
bytes32 _root,
|
||||
bytes32 _nullifierHash,
|
||||
address payable _recipient,
|
||||
address payable _relayer,
|
||||
uint256 _fee,
|
||||
uint256 _refund
|
||||
) external payable {
|
||||
Instance memory instance = instances[_tornado];
|
||||
require(instance.state != InstanceState.DISABLED, "The instance is not supported");
|
||||
|
||||
_tornado.withdraw{ value: msg.value }(_proof, _root, _nullifierHash, _recipient, _relayer, _fee, _refund);
|
||||
if (instance.state == InstanceState.MINEABLE) {
|
||||
tornadoTrees.registerWithdrawal(address(_tornado), _nullifierHash);
|
||||
}
|
||||
}
|
||||
|
||||
function backupNotes(bytes[] calldata _encryptedNotes) external {
|
||||
for (uint256 i = 0; i < _encryptedNotes.length; i++) {
|
||||
emit EncryptedNote(msg.sender, _encryptedNotes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function updateInstance(Tornado calldata _tornado) external onlyGovernance {
|
||||
_updateInstance(_tornado);
|
||||
}
|
||||
|
||||
function setTornadoTreesContract(ITornadoTrees _tornadoTrees) external onlyGovernance {
|
||||
tornadoTrees = _tornadoTrees;
|
||||
emit TornadoTreesUpdated(_tornadoTrees);
|
||||
}
|
||||
|
||||
/// @dev Method to claim junk and accidentally sent tokens
|
||||
function rescueTokens(
|
||||
IERC20 _token,
|
||||
address payable _to,
|
||||
uint256 _amount
|
||||
) external onlyGovernance {
|
||||
require(_to != address(0), "TORN: can not send to zero address");
|
||||
|
||||
if (_token == IERC20(0)) {
|
||||
// for Ether
|
||||
uint256 totalBalance = address(this).balance;
|
||||
uint256 balance = Math.min(totalBalance, _amount);
|
||||
_to.transfer(balance);
|
||||
} else {
|
||||
// any other erc20
|
||||
uint256 totalBalance = _token.balanceOf(address(this));
|
||||
uint256 balance = Math.min(totalBalance, _amount);
|
||||
require(balance > 0, "TORN: trying to send 0 balance");
|
||||
_token.safeTransfer(_to, balance);
|
||||
}
|
||||
}
|
||||
|
||||
function _updateInstance(Tornado memory _tornado) internal {
|
||||
instances[_tornado.addr] = _tornado.instance;
|
||||
if (_tornado.instance.isERC20) {
|
||||
IERC20 token = IERC20(_tornado.addr.token());
|
||||
require(token == _tornado.instance.token, "Incorrect token");
|
||||
uint256 allowance = token.allowance(address(this), address(_tornado.addr));
|
||||
|
||||
if (_tornado.instance.state != InstanceState.DISABLED && allowance == 0) {
|
||||
token.safeApprove(address(_tornado.addr), uint256(-1));
|
||||
} else if (_tornado.instance.state == InstanceState.DISABLED && allowance != 0) {
|
||||
token.safeApprove(address(_tornado.addr), 0);
|
||||
}
|
||||
}
|
||||
emit InstanceStateUpdated(_tornado.addr, _tornado.instance.state);
|
||||
}
|
||||
}
|
@ -5,9 +5,9 @@ require('@nomiclabs/hardhat-waffle')
|
||||
require('hardhat-log-remover')
|
||||
require('solidity-coverage')
|
||||
|
||||
require('./tasks/deploy_proposal.js')
|
||||
require('./tasks/deploy_factory_proposal.js')
|
||||
require('./tasks/propose_proposal.js')
|
||||
// require('./tasks/deploy_proposal.js')
|
||||
// require('./tasks/deploy_factory_proposal.js')
|
||||
// require('./tasks/propose_proposal.js')
|
||||
/**
|
||||
* @type import('hardhat/config').HardhatUserConfig
|
||||
*/
|
||||
@ -19,7 +19,7 @@ module.exports = {
|
||||
settings: {
|
||||
optimizer: {
|
||||
enabled: true,
|
||||
runs: 2000,
|
||||
runs: 200,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -28,7 +28,7 @@ module.exports = {
|
||||
settings: {
|
||||
optimizer: {
|
||||
enabled: true,
|
||||
runs: 2000,
|
||||
runs: 200,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
25
package.json
25
package.json
@ -1,24 +1,25 @@
|
||||
{
|
||||
"name": "tornado-instances",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"start": "node src/index.js",
|
||||
"eslint": "eslint --ext .js --ignore-path .gitignore .",
|
||||
"prettier:check": "prettier --check . --config .prettierrc",
|
||||
"prettier:fix": "prettier --write . --config .prettierrc",
|
||||
"lint": "yarn eslint && yarn prettier:check",
|
||||
"deploy:proposal": "yarn hardhat --network mainnet deploy_proposal --factory-address",
|
||||
"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",
|
||||
"compile": "yarn hardhat compile",
|
||||
"test": "yarn hardhat test",
|
||||
"f:test": "yarn test && yarn clean",
|
||||
"clean": "yarn prettier:fix && yarn lint",
|
||||
"coverage": "yarn hardhat coverage --testfiles \"test/*.js\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@openzeppelin/contracts": "3.4.2",
|
||||
"@openzeppelin/upgrades-core": "^1.0.1",
|
||||
"torn-token": "^1.0.4",
|
||||
"tornado-cli": "^0.0.1",
|
||||
"tornado-core": "https://github.com/tornadocash/tornado-core.git",
|
||||
"tornado-governance": "2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
||||
"@nomiclabs/hardhat-etherscan": "^2.1.4",
|
||||
@ -39,13 +40,5 @@
|
||||
"solhint-plugin-prettier": "^0.0.5",
|
||||
"solidity-coverage": "^0.7.17",
|
||||
"websnark": "^0.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@openzeppelin/contracts": "3.4.2",
|
||||
"@openzeppelin/upgrades-core": "^1.0.1",
|
||||
"torn-token": "^1.0.4",
|
||||
"tornado-cli": "^0.0.1",
|
||||
"tornado-core": "https://github.com/tornadocash/tornado-core.git",
|
||||
"tornado-governance": "^1.0.2"
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
module.exports = [
|
||||
{
|
||||
tokenAddress: '0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919',
|
||||
denomination: '33333333333333333333',
|
||||
symbol: 'RAI',
|
||||
decimals: 18,
|
||||
},
|
||||
{
|
||||
tokenAddress: '0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919',
|
||||
denomination: '333333333333333333333',
|
||||
symbol: 'RAI',
|
||||
decimals: 18,
|
||||
},
|
||||
{
|
||||
tokenAddress: '0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919',
|
||||
denomination: '3333333333333333333333',
|
||||
symbol: 'RAI',
|
||||
decimals: 18,
|
||||
},
|
||||
{
|
||||
tokenAddress: '0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919',
|
||||
denomination: '33333333333333333333333',
|
||||
symbol: 'RAI',
|
||||
decimals: 18,
|
||||
},
|
||||
]
|
298
yarn.lock
298
yarn.lock
@ -1232,6 +1232,13 @@
|
||||
dependencies:
|
||||
"@ethersproject/logger" "^5.5.0"
|
||||
|
||||
"@ethersproject/networks@5.5.2":
|
||||
version "5.5.2"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.5.2.tgz#784c8b1283cd2a931114ab428dae1bd00c07630b"
|
||||
integrity sha512-NEqPxbGBfy6O3x4ZTISb90SjEDkWYDUbEeIFhJly0F7sZjoQMnj5KYzMSkMkLKZ+1fGpx00EDpHQCy6PrDupkQ==
|
||||
dependencies:
|
||||
"@ethersproject/logger" "^5.5.0"
|
||||
|
||||
"@ethersproject/networks@^5.4.0":
|
||||
version "5.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.4.2.tgz#2247d977626e97e2c3b8ee73cd2457babde0ce35"
|
||||
@ -1319,6 +1326,31 @@
|
||||
bech32 "1.1.4"
|
||||
ws "7.4.6"
|
||||
|
||||
"@ethersproject/providers@5.5.3":
|
||||
version "5.5.3"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.5.3.tgz#56c2b070542ac44eb5de2ed3cf6784acd60a3130"
|
||||
integrity sha512-ZHXxXXXWHuwCQKrgdpIkbzMNJMvs+9YWemanwp1fA7XZEv7QlilseysPvQe0D7Q7DlkJX/w/bGA1MdgK2TbGvA==
|
||||
dependencies:
|
||||
"@ethersproject/abstract-provider" "^5.5.0"
|
||||
"@ethersproject/abstract-signer" "^5.5.0"
|
||||
"@ethersproject/address" "^5.5.0"
|
||||
"@ethersproject/basex" "^5.5.0"
|
||||
"@ethersproject/bignumber" "^5.5.0"
|
||||
"@ethersproject/bytes" "^5.5.0"
|
||||
"@ethersproject/constants" "^5.5.0"
|
||||
"@ethersproject/hash" "^5.5.0"
|
||||
"@ethersproject/logger" "^5.5.0"
|
||||
"@ethersproject/networks" "^5.5.0"
|
||||
"@ethersproject/properties" "^5.5.0"
|
||||
"@ethersproject/random" "^5.5.0"
|
||||
"@ethersproject/rlp" "^5.5.0"
|
||||
"@ethersproject/sha2" "^5.5.0"
|
||||
"@ethersproject/strings" "^5.5.0"
|
||||
"@ethersproject/transactions" "^5.5.0"
|
||||
"@ethersproject/web" "^5.5.0"
|
||||
bech32 "1.1.4"
|
||||
ws "7.4.6"
|
||||
|
||||
"@ethersproject/random@5.4.0", "@ethersproject/random@^5.4.0":
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.4.0.tgz#9cdde60e160d024be39cc16f8de3b9ce39191e16"
|
||||
@ -1335,6 +1367,14 @@
|
||||
"@ethersproject/bytes" "^5.5.0"
|
||||
"@ethersproject/logger" "^5.5.0"
|
||||
|
||||
"@ethersproject/random@5.5.1":
|
||||
version "5.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.5.1.tgz#7cdf38ea93dc0b1ed1d8e480ccdaf3535c555415"
|
||||
integrity sha512-YaU2dQ7DuhL5Au7KbcQLHxcRHfgyNgvFV4sQOo0HrtW3Zkrc9ctWNz8wXQ4uCSfSDsqX2vcjhroxU5RQRV0nqA==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.5.0"
|
||||
"@ethersproject/logger" "^5.5.0"
|
||||
|
||||
"@ethersproject/rlp@5.4.0", "@ethersproject/rlp@^5.4.0":
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.4.0.tgz#de61afda5ff979454e76d3b3310a6c32ad060931"
|
||||
@ -1546,6 +1586,17 @@
|
||||
"@ethersproject/properties" "^5.5.0"
|
||||
"@ethersproject/strings" "^5.5.0"
|
||||
|
||||
"@ethersproject/web@5.5.1":
|
||||
version "5.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.5.1.tgz#cfcc4a074a6936c657878ac58917a61341681316"
|
||||
integrity sha512-olvLvc1CB12sREc1ROPSHTdFCdvMh0J5GSJYiQg2D0hdD4QmJDy8QYDb1CvoqD/bF1c++aeKv2sR5uduuG9dQg==
|
||||
dependencies:
|
||||
"@ethersproject/base64" "^5.5.0"
|
||||
"@ethersproject/bytes" "^5.5.0"
|
||||
"@ethersproject/logger" "^5.5.0"
|
||||
"@ethersproject/properties" "^5.5.0"
|
||||
"@ethersproject/strings" "^5.5.0"
|
||||
|
||||
"@ethersproject/wordlists@5.4.0", "@ethersproject/wordlists@^5.4.0":
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.4.0.tgz#f34205ec3bbc9e2c49cadaee774cf0b07e7573d7"
|
||||
@ -1568,6 +1619,37 @@
|
||||
"@ethersproject/properties" "^5.5.0"
|
||||
"@ethersproject/strings" "^5.5.0"
|
||||
|
||||
"@gnosis.pm/ido-contracts@^0.5.0":
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@gnosis.pm/ido-contracts/-/ido-contracts-0.5.0.tgz#83de88dece517d5f1069ec32bd2eebd1857ef3ac"
|
||||
integrity sha512-4q7bB4c+7zFvIlolg/Xo1rRFcecAO+zLdIQ2am5zXKnii0Txz3Ki4yXzg7/nbBHMPZZANLmVgXe0ZDiGS5OsIw==
|
||||
dependencies:
|
||||
"@gnosis.pm/solidity-data-structures" "^1.3.4"
|
||||
"@types/yargs" "^15.0.10"
|
||||
argv "^0.0.2"
|
||||
axios "^0.21.1"
|
||||
bn.js "^5.1.1"
|
||||
dotenv "^8.2.0"
|
||||
ethers "^5.0.22"
|
||||
solc "0.6.8"
|
||||
yargs "^16.1.1"
|
||||
|
||||
"@gnosis.pm/solidity-data-structures@^1.3.4":
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/@gnosis.pm/solidity-data-structures/-/solidity-data-structures-1.3.5.tgz#a38cab984a5a4c7d379454d5e82a2ac2f1a6b65e"
|
||||
integrity sha512-qU32sUlH1cE26uhSSTbCYpskYzMm4KBXaIZdpu9v2xsO6jjedgfg9rKxJcor1V4ZRBp4EQyFqWzPx7fPTTPoUQ==
|
||||
dependencies:
|
||||
"@gnosis.pm/util-contracts" "^2.0.4"
|
||||
ethereumjs-util "^6.1.0"
|
||||
merkletreejs "0.0.22"
|
||||
|
||||
"@gnosis.pm/util-contracts@^2.0.4":
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@gnosis.pm/util-contracts/-/util-contracts-2.0.7.tgz#b28073890a6a6be8458a7d7952c8541788fd020f"
|
||||
integrity sha512-+8V0C/E4aGMudeMQBNDLidE3GwfM4XSySuT39wON8wpj9ocNyIsV4U+4YTfEOyUQ9PafKloWr78W5OhkOX9eqQ==
|
||||
dependencies:
|
||||
"@truffle/hdwallet-provider" "^1.0.42"
|
||||
|
||||
"@graphql-tools/batch-delegate@^6.2.4", "@graphql-tools/batch-delegate@^6.2.6":
|
||||
version "6.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@graphql-tools/batch-delegate/-/batch-delegate-6.2.6.tgz#fbea98dc825f87ef29ea5f3f371912c2a2aa2f2c"
|
||||
@ -2051,6 +2133,11 @@
|
||||
"@types/sinon-chai" "^3.2.3"
|
||||
"@types/web3" "1.0.19"
|
||||
|
||||
"@openzeppelin/contracts@3.2.0-rc.0":
|
||||
version "3.2.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.2.0-rc.0.tgz#1f39e49df5f7a7b42fd49343ac1d758bbd24b826"
|
||||
integrity sha512-EcEho5UFNZN1ZUHuD5ka38qgs+XWlzBM1FFfpu4YNVoo0xtwWeg7X52jm8pK+NYq8tJAI8ySjGYPM+4S5+N8iA==
|
||||
|
||||
"@openzeppelin/contracts@3.4.2", "@openzeppelin/contracts@^3.2.0-rc.0", "@openzeppelin/contracts@^3.4.1":
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.2.tgz#d81f786fda2871d1eb8a8c5a73e455753ba53527"
|
||||
@ -2818,6 +2905,20 @@
|
||||
ethereumjs-util "^6.1.0"
|
||||
ethereumjs-wallet "^1.0.1"
|
||||
|
||||
"@truffle/hdwallet-provider@^1.0.42":
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@truffle/hdwallet-provider/-/hdwallet-provider-1.7.0.tgz#5cfa8bc67c2a30b3943d3dab78f74c6a191cde02"
|
||||
integrity sha512-nT7BPJJ2jPCLJc5uZdVtRnRMny5he5d3kO9Hi80ZSqe5xlnK905grBptM/+CwOfbeqHKQirI1btwm6r3wIBM8A==
|
||||
dependencies:
|
||||
"@ethereumjs/common" "^2.4.0"
|
||||
"@ethereumjs/tx" "^3.3.0"
|
||||
"@trufflesuite/web3-provider-engine" "15.0.14"
|
||||
eth-sig-util "^3.0.1"
|
||||
ethereum-cryptography "^0.1.3"
|
||||
ethereum-protocol "^1.0.1"
|
||||
ethereumjs-util "^6.1.0"
|
||||
ethereumjs-wallet "^1.0.1"
|
||||
|
||||
"@truffle/interface-adapter@^0.5.8":
|
||||
version "0.5.8"
|
||||
resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.8.tgz#76cfd34374d85849e1164de1a3d5a3dce0dc5d01"
|
||||
@ -3014,6 +3115,34 @@
|
||||
xhr "^2.2.0"
|
||||
xtend "^4.0.1"
|
||||
|
||||
"@trufflesuite/web3-provider-engine@15.0.14":
|
||||
version "15.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@trufflesuite/web3-provider-engine/-/web3-provider-engine-15.0.14.tgz#8f9696f434585cc0ab2e57c312090c1f138bc471"
|
||||
integrity sha512-6/LoWvNMxYf0oaYzJldK2a9AdnkAdIeJhHW4nuUBAeO29eK9xezEaEYQ0ph1QRTaICxGxvn+1Azp4u8bQ8NEZw==
|
||||
dependencies:
|
||||
"@ethereumjs/tx" "^3.3.0"
|
||||
"@trufflesuite/eth-json-rpc-filters" "^4.1.2-1"
|
||||
"@trufflesuite/eth-json-rpc-infura" "^4.0.3-0"
|
||||
"@trufflesuite/eth-json-rpc-middleware" "^4.4.2-1"
|
||||
"@trufflesuite/eth-sig-util" "^1.4.2"
|
||||
async "^2.5.0"
|
||||
backoff "^2.5.0"
|
||||
clone "^2.0.0"
|
||||
cross-fetch "^2.1.0"
|
||||
eth-block-tracker "^4.4.2"
|
||||
eth-json-rpc-errors "^2.0.2"
|
||||
ethereumjs-block "^1.2.2"
|
||||
ethereumjs-util "^5.1.5"
|
||||
ethereumjs-vm "^2.3.4"
|
||||
json-stable-stringify "^1.0.1"
|
||||
promise-to-callback "^1.0.0"
|
||||
readable-stream "^2.2.9"
|
||||
request "^2.85.0"
|
||||
semaphore "^1.0.3"
|
||||
ws "^5.1.1"
|
||||
xhr "^2.2.0"
|
||||
xtend "^4.0.1"
|
||||
|
||||
"@typechain/ethers-v5@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810"
|
||||
@ -3354,6 +3483,18 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/yargs-parser@*":
|
||||
version "20.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129"
|
||||
integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==
|
||||
|
||||
"@types/yargs@^15.0.10":
|
||||
version "15.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06"
|
||||
integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@types/zen-observable@0.8.3":
|
||||
version "0.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.3.tgz#781d360c282436494b32fe7d9f7f8e64b3118aa3"
|
||||
@ -3971,6 +4112,11 @@ argsarray@0.0.1, argsarray@^0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/argsarray/-/argsarray-0.0.1.tgz#6e7207b4ecdb39b0af88303fa5ae22bda8df61cb"
|
||||
integrity sha1-bnIHtOzbObCviDA/pa4ivajfYcs=
|
||||
|
||||
argv@^0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/argv/-/argv-0.0.2.tgz#ecbd16f8949b157183711b1bda334f37840185ab"
|
||||
integrity sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=
|
||||
|
||||
arr-diff@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
|
||||
@ -4214,6 +4360,13 @@ axios@^0.20.0:
|
||||
dependencies:
|
||||
follow-redirects "^1.10.0"
|
||||
|
||||
axios@^0.21.1:
|
||||
version "0.21.4"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
|
||||
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.0"
|
||||
|
||||
babel-code-frame@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
|
||||
@ -5377,6 +5530,11 @@ buffer-pipe@0.0.3:
|
||||
dependencies:
|
||||
safe-buffer "^5.1.2"
|
||||
|
||||
buffer-reverse@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-reverse/-/buffer-reverse-1.0.1.tgz#49283c8efa6f901bc01fa3304d06027971ae2f60"
|
||||
integrity sha1-SSg8jvpvkBvAH6MwTQYCeXGuL2A=
|
||||
|
||||
buffer-to-arraybuffer@^0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a"
|
||||
@ -5976,6 +6134,15 @@ cliui@^6.0.0:
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^6.2.0"
|
||||
|
||||
cliui@^7.0.2:
|
||||
version "7.0.4"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
|
||||
integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
|
||||
dependencies:
|
||||
string-width "^4.2.0"
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
clone-buffer@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58"
|
||||
@ -6429,6 +6596,11 @@ crypto-browserify@3.12.0, crypto-browserify@^3.0.0, crypto-browserify@^3.11.0:
|
||||
randombytes "^2.0.0"
|
||||
randomfill "^1.0.3"
|
||||
|
||||
crypto-js@^3.1.9-1:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.3.0.tgz#846dd1cce2f68aacfa156c8578f926a609b7976b"
|
||||
integrity sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==
|
||||
|
||||
css-select@^4.1.3:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.1.3.tgz#a70440f70317f2669118ad74ff105e65849c7067"
|
||||
@ -8234,6 +8406,42 @@ ethers@^5.0.13:
|
||||
"@ethersproject/web" "5.5.0"
|
||||
"@ethersproject/wordlists" "5.5.0"
|
||||
|
||||
ethers@^5.0.22:
|
||||
version "5.5.4"
|
||||
resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.5.4.tgz#e1155b73376a2f5da448e4a33351b57a885f4352"
|
||||
integrity sha512-N9IAXsF8iKhgHIC6pquzRgPBJEzc9auw3JoRkaKe+y4Wl/LFBtDDunNe7YmdomontECAcC5APaAgWZBiu1kirw==
|
||||
dependencies:
|
||||
"@ethersproject/abi" "5.5.0"
|
||||
"@ethersproject/abstract-provider" "5.5.1"
|
||||
"@ethersproject/abstract-signer" "5.5.0"
|
||||
"@ethersproject/address" "5.5.0"
|
||||
"@ethersproject/base64" "5.5.0"
|
||||
"@ethersproject/basex" "5.5.0"
|
||||
"@ethersproject/bignumber" "5.5.0"
|
||||
"@ethersproject/bytes" "5.5.0"
|
||||
"@ethersproject/constants" "5.5.0"
|
||||
"@ethersproject/contracts" "5.5.0"
|
||||
"@ethersproject/hash" "5.5.0"
|
||||
"@ethersproject/hdnode" "5.5.0"
|
||||
"@ethersproject/json-wallets" "5.5.0"
|
||||
"@ethersproject/keccak256" "5.5.0"
|
||||
"@ethersproject/logger" "5.5.0"
|
||||
"@ethersproject/networks" "5.5.2"
|
||||
"@ethersproject/pbkdf2" "5.5.0"
|
||||
"@ethersproject/properties" "5.5.0"
|
||||
"@ethersproject/providers" "5.5.3"
|
||||
"@ethersproject/random" "5.5.1"
|
||||
"@ethersproject/rlp" "5.5.0"
|
||||
"@ethersproject/sha2" "5.5.0"
|
||||
"@ethersproject/signing-key" "5.5.0"
|
||||
"@ethersproject/solidity" "5.5.0"
|
||||
"@ethersproject/strings" "5.5.0"
|
||||
"@ethersproject/transactions" "5.5.0"
|
||||
"@ethersproject/units" "5.5.0"
|
||||
"@ethersproject/wallet" "5.5.0"
|
||||
"@ethersproject/web" "5.5.1"
|
||||
"@ethersproject/wordlists" "5.5.0"
|
||||
|
||||
ethjs-unit@0.1.6:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699"
|
||||
@ -8836,6 +9044,11 @@ follow-redirects@^1.12.1:
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43"
|
||||
integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==
|
||||
|
||||
follow-redirects@^1.14.0:
|
||||
version "1.14.8"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
|
||||
integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
|
||||
|
||||
for-each@^0.3.3, for-each@~0.3.3:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
||||
@ -9118,7 +9331,7 @@ get-caller-file@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
|
||||
integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
|
||||
|
||||
get-caller-file@^2.0.1:
|
||||
get-caller-file@^2.0.1, get-caller-file@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
@ -10362,7 +10575,7 @@ is-buffer@^1.1.0, is-buffer@^1.1.5:
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
||||
|
||||
is-buffer@~2.0.3:
|
||||
is-buffer@^2.0.3, is-buffer@~2.0.3:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191"
|
||||
integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==
|
||||
@ -12176,6 +12389,16 @@ merkle-patricia-tree@^4.2.0:
|
||||
rlp "^2.2.4"
|
||||
semaphore-async-await "^1.5.1"
|
||||
|
||||
merkletreejs@0.0.22:
|
||||
version "0.0.22"
|
||||
resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.0.22.tgz#ccc1008cdfa8f5a01a4f735f91c7a29c34070b6c"
|
||||
integrity sha512-oZF3PIoRRmbG1ikN/3c0n0i421ZzdyOpNbm6wDNt5LVLIpW2FCany8ERwOyAZq83vM+Nx1zTp7Br7cIpicWzNQ==
|
||||
dependencies:
|
||||
buffer-reverse "^1.0.1"
|
||||
crypto-js "^3.1.9-1"
|
||||
is-buffer "^2.0.3"
|
||||
treeify "^1.1.0"
|
||||
|
||||
meros@1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/meros/-/meros-1.1.4.tgz#c17994d3133db8b23807f62bec7f0cb276cfd948"
|
||||
@ -15581,6 +15804,20 @@ socketcluster-client@^14.2.1:
|
||||
uuid "3.2.1"
|
||||
ws "^7.5.0"
|
||||
|
||||
solc@0.6.8:
|
||||
version "0.6.8"
|
||||
resolved "https://registry.yarnpkg.com/solc/-/solc-0.6.8.tgz#accf03634554938e166ba9b9853d17ca5c728131"
|
||||
integrity sha512-7URBAisWVjO7dwWNpEkQ5dpRSpSF4Wm0aD5EB82D5BQKh+q7jhOxhgkG4K5gax/geM0kPZUAxnaLcgl2ZXBgMQ==
|
||||
dependencies:
|
||||
command-exists "^1.2.8"
|
||||
commander "3.0.2"
|
||||
fs-extra "^0.30.0"
|
||||
js-sha3 "0.8.0"
|
||||
memorystream "^0.3.1"
|
||||
require-from-string "^2.0.0"
|
||||
semver "^5.5.0"
|
||||
tmp "0.0.33"
|
||||
|
||||
solc@0.7.3:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a"
|
||||
@ -16593,10 +16830,22 @@ tornado-cli@^0.0.1:
|
||||
web3-utils "^1.3.4"
|
||||
websnark "git+https://github.com/tornadocash/websnark.git#4c0af6a8b65aabea3c09f377f63c44e7a58afa6d"
|
||||
|
||||
tornado-governance@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/tornado-governance/-/tornado-governance-1.0.2.tgz#c6f32d3ccdf777937eab0f01ac7bab8e5845a0be"
|
||||
integrity sha512-Kk+1FuG30FNeJ6Xxym4uDWb2s1stymn9KsYVu/NuQhYCJpn06MimHT8OQgY5kh0pcYikPH+45jVNX+luoDZoFg==
|
||||
tornado-governance@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tornado-governance/-/tornado-governance-2.0.0.tgz#07f6b52fe86430815ee9603d1b36ec411202cb34"
|
||||
integrity sha512-JmXzxEBhGGJDxsRDp1M0RkN4ZWmm9MzrIy1agUbMEwQUXtRirY+rK4sYDXEvSRJIj8qDl3Pr8nYwny3O2sNRnA==
|
||||
dependencies:
|
||||
"@ethersproject/bignumber" "^5.5.0"
|
||||
"@gnosis.pm/ido-contracts" "^0.5.0"
|
||||
"@openzeppelin/contracts" "3.2.0-rc.0"
|
||||
"@openzeppelin/upgrades-core" "^1.0.1"
|
||||
torn-token "^1.0.4"
|
||||
tornado-governance "^1.0.3"
|
||||
|
||||
tornado-governance@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tornado-governance/-/tornado-governance-1.0.3.tgz#2b11ebe698af42cdec35ff77583ac4c5d65847f6"
|
||||
integrity sha512-T1PYCDCzbabjv0lRKBLIIshmDMKwckrwZQzu8nAXsHygNrRtg052QP5YvGjRx0JpfKEBnf5fKjljC3RZAaA8rQ==
|
||||
dependencies:
|
||||
"@openzeppelin/contracts" "^3.2.0-rc.0"
|
||||
"@openzeppelin/upgrades-core" "^1.0.1"
|
||||
@ -16624,6 +16873,11 @@ tr46@~0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
|
||||
|
||||
treeify@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8"
|
||||
integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==
|
||||
|
||||
trim-right@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
|
||||
@ -18788,6 +19042,15 @@ wrap-ansi@^6.2.0:
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
@ -18920,6 +19183,11 @@ y18n@^3.2.1:
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
|
||||
integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
|
||||
|
||||
y18n@^5.0.5:
|
||||
version "5.0.8"
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
||||
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
|
||||
|
||||
yaeti@^0.0.6:
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577"
|
||||
@ -18980,6 +19248,11 @@ yargs-parser@^2.4.0, yargs-parser@^2.4.1:
|
||||
camelcase "^3.0.0"
|
||||
lodash.assign "^4.0.6"
|
||||
|
||||
yargs-parser@^20.2.2:
|
||||
version "20.2.9"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
|
||||
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
|
||||
|
||||
yargs-parser@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9"
|
||||
@ -19110,6 +19383,19 @@ yargs@^15.3.1:
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^18.1.2"
|
||||
|
||||
yargs@^16.1.1:
|
||||
version "16.2.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
|
||||
integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
|
||||
dependencies:
|
||||
cliui "^7.0.2"
|
||||
escalade "^3.1.1"
|
||||
get-caller-file "^2.0.5"
|
||||
require-directory "^2.1.1"
|
||||
string-width "^4.2.0"
|
||||
y18n "^5.0.5"
|
||||
yargs-parser "^20.2.2"
|
||||
|
||||
yargs@^4.7.1:
|
||||
version "4.8.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0"
|
||||
|
Loading…
Reference in New Issue
Block a user