diff --git a/contracts/AdminUpgradeableProxy.sol b/contracts/AdminUpgradeableProxy.sol new file mode 100644 index 0000000..ca1649d --- /dev/null +++ b/contracts/AdminUpgradeableProxy.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.6.0; + +import "@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol"; + +/** + * @dev TransparentUpgradeableProxy where admin is allowed to call implementation methods. + */ +contract AdminUpgradeableProxy is TransparentUpgradeableProxy { + /** + * @dev Initializes an upgradeable proxy backed by the implementation at `_logic`. + */ + constructor(address _logic, bytes memory _data) public payable TransparentUpgradeableProxy(_logic, msg.sender, _data) {} + + /** + * @dev Override to allow admin access the fallback function. + */ + function _beforeFallback() internal override {} +} diff --git a/contracts/TornadoTrees.sol b/contracts/TornadoTrees.sol index 587ca80..cd2ef5b 100644 --- a/contracts/TornadoTrees.sol +++ b/contracts/TornadoTrees.sol @@ -5,8 +5,9 @@ pragma experimental ABIEncoderV2; import "./interfaces/ITornadoTreesV1.sol"; import "./interfaces/IBatchTreeUpdateVerifier.sol"; +import "@openzeppelin/upgrades-core/contracts/Initializable.sol"; -contract TornadoTrees { +contract TornadoTrees is Initializable { address public immutable governance; bytes32 public depositRoot; bytes32 public previousDepositRoot; @@ -61,32 +62,20 @@ contract TornadoTrees { constructor( address _governance, - address _tornadoProxy, ITornadoTreesV1 _tornadoTreesV1, - IBatchTreeUpdateVerifier _treeUpdateVerifier, SearchParams memory _searchParams ) public { governance = _governance; - tornadoProxy = _tornadoProxy; - treeUpdateVerifier = _treeUpdateVerifier; tornadoTreesV1 = _tornadoTreesV1; - depositRoot = _tornadoTreesV1.depositRoot(); - uint256 lastDepositLeaf = _tornadoTreesV1.lastProcessedDepositLeaf(); - require(lastDepositLeaf % CHUNK_SIZE == 0, "Incorrect TornadoTrees state"); - lastProcessedDepositLeaf = lastDepositLeaf; - depositsLength = depositsV1Length = findArrayLength( + depositsV1Length = findArrayLength( _tornadoTreesV1, "deposits(uint256)", _searchParams.depositsFrom, _searchParams.depositsStep ); - withdrawalRoot = _tornadoTreesV1.withdrawalRoot(); - uint256 lastWithdrawalLeaf = _tornadoTreesV1.lastProcessedWithdrawalLeaf(); - require(lastWithdrawalLeaf % CHUNK_SIZE == 0, "Incorrect TornadoTrees state"); - lastProcessedWithdrawalLeaf = lastWithdrawalLeaf; - withdrawalsLength = withdrawalsV1Length = findArrayLength( + withdrawalsV1Length = findArrayLength( _tornadoTreesV1, "withdrawals(uint256)", _searchParams.withdrawalsFrom, @@ -94,6 +83,23 @@ contract TornadoTrees { ); } + function initialize(address _tornadoProxy, IBatchTreeUpdateVerifier _treeUpdateVerifier) public initializer onlyGovernance { + tornadoProxy = _tornadoProxy; + treeUpdateVerifier = _treeUpdateVerifier; + + depositRoot = tornadoTreesV1.depositRoot(); + uint256 lastDepositLeaf = tornadoTreesV1.lastProcessedDepositLeaf(); + require(lastDepositLeaf % CHUNK_SIZE == 0, "Incorrect TornadoTrees state"); + lastProcessedDepositLeaf = lastDepositLeaf; + depositsLength = depositsV1Length; + + withdrawalRoot = tornadoTreesV1.withdrawalRoot(); + uint256 lastWithdrawalLeaf = tornadoTreesV1.lastProcessedWithdrawalLeaf(); + require(lastWithdrawalLeaf % CHUNK_SIZE == 0, "Incorrect TornadoTrees state"); + lastProcessedWithdrawalLeaf = lastWithdrawalLeaf; + withdrawalsLength = withdrawalsV1Length; + } + // todo make things internal /// @dev There is no array length getter for deposit and withdrawal arrays /// in previous contract, so we have to find them length manually diff --git a/contracts/mocks/TornadoTreesMock.sol b/contracts/mocks/TornadoTreesMock.sol index 727d379..d2e3b36 100644 --- a/contracts/mocks/TornadoTreesMock.sol +++ b/contracts/mocks/TornadoTreesMock.sol @@ -12,11 +12,9 @@ contract TornadoTreesMock is TornadoTrees { constructor( address _governance, - address _tornadoProxy, ITornadoTreesV1 _tornadoTreesV1, - IBatchTreeUpdateVerifier _treeUpdateVerifier, SearchParams memory _searchParams - ) public TornadoTrees(_governance, _tornadoProxy, _tornadoTreesV1, _treeUpdateVerifier, _searchParams) {} + ) public TornadoTrees(_governance, _tornadoTreesV1, _searchParams) {} function setBlockNumber(uint256 _blockNumber) public { currentBlock = _blockNumber; diff --git a/package.json b/package.json index 5c9f5c8..e6bbc4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tornado-trees", - "version": "0.0.6", + "version": "0.0.7", "main": "src/index.js", "repository": "https://github.com/tornadocash/tornado-trees.git", "author": "Tornadocash team ", @@ -39,6 +39,8 @@ "torn-token": "^1.0.0" }, "dependencies": { + "@openzeppelin/contracts": "^3.4.0", + "@openzeppelin/upgrades-core": "^1.5.1", "circom": "^0.5.38", "circom_runtime": "^0.1.12", "circomlib": "git+https://github.com/tornadocash/circomlib.git#d20d53411d1bef61f38c99a8b36d5d0cc4836aa1", diff --git a/test/binarySearch.test.js b/test/binarySearch.test.js index d25f12c..4360bf1 100644 --- a/test/binarySearch.test.js +++ b/test/binarySearch.test.js @@ -18,18 +18,13 @@ describe('findArrayLength', () => { await publicArray.setWithdrawals(depositsEven) const TornadoTrees = await ethers.getContractFactory('TornadoTreesMock') - tornadoTrees = await TornadoTrees.deploy( - operator.address, - tornadoProxy.address, - publicArray.address, - publicArray.address, - { - depositsFrom: 3, - depositsStep: 3, - withdrawalsFrom: 2, - withdrawalsStep: 2, - }, - ) + tornadoTrees = await TornadoTrees.deploy(operator.address, publicArray.address, { + depositsFrom: 3, + depositsStep: 3, + withdrawalsFrom: 2, + withdrawalsStep: 2, + }) + await tornadoTrees.initialize(tornadoProxy.address, publicArray.address) }) it('should work for even array', async () => { diff --git a/test/tornadoTrees.test.js b/test/tornadoTrees.test.js index 6f55cad..bc11ead 100644 --- a/test/tornadoTrees.test.js +++ b/test/tornadoTrees.test.js @@ -71,18 +71,13 @@ describe('TornadoTrees', function () { } } const TornadoTrees = await ethers.getContractFactory('TornadoTreesMock') - tornadoTrees = await TornadoTrees.deploy( - operator.address, - tornadoProxy.address, - tornadoTreesV1.address, - verifier.address, - { - depositsFrom: 1, - depositsStep: 1, - withdrawalsFrom: 2, - withdrawalsStep: 2, - }, - ) + tornadoTrees = await TornadoTrees.deploy(operator.address, tornadoTreesV1.address, { + depositsFrom: 1, + depositsStep: 1, + withdrawalsFrom: 2, + withdrawalsStep: 2, + }) + await tornadoTrees.initialize(tornadoProxy.address, verifier.address) depositDataEventFilter = tornadoTrees.filters.DepositData() }) @@ -160,18 +155,13 @@ describe('TornadoTrees', function () { } const TornadoTrees = await ethers.getContractFactory('TornadoTreesMock') - const newTornadoTrees = await TornadoTrees.deploy( - operator.address, - tornadoProxy.address, - tornadoTreesV1.address, - verifier.address, - { - depositsFrom: 1, - depositsStep: 1, - withdrawalsFrom: 2, - withdrawalsStep: 2, - }, - ) + const newTornadoTrees = await TornadoTrees.deploy(operator.address, tornadoTreesV1.address, { + depositsFrom: 1, + depositsStep: 1, + withdrawalsFrom: 2, + withdrawalsStep: 2, + }) + await newTornadoTrees.initialize(tornadoProxy.address, verifier.address) // load first batchSize deposits let { input, args } = controller.batchTreeUpdate(tree, depositEvents) diff --git a/yarn.lock b/yarn.lock index dd9dcb4..52f4ae4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -593,6 +593,27 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.3.0.tgz#ffdb693c5c349fc33bba420248dd3ac0a2d7c408" integrity sha512-AemZEsQYtUp1WRkcmZm1div5ORfTpLquLaziCIrSagjxyKdmObxuaY1yjQ5SHFMctR8rLwp706NXTbiIRJg7pw== +"@openzeppelin/contracts@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.0.tgz#9a1669ad5f9fdfb6e273bb5a4fed10cb4cc35eb0" + integrity sha512-qh+EiHWzfY/9CORr+eRUkeEUP1WiFUcq3974bLHwyYzLBUtK6HPaMkIUHi74S1rDTZ0sNz42DwPc5A4IJvN3rg== + +"@openzeppelin/upgrades-core@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.5.1.tgz#2165f0c2961cc748e7d1c2bce1ba96589d31390b" + integrity sha512-rL0h/+Yfcky98XaxLRcxKunmC2uVP+dr9tVxzZfbjDpIco7VkmyODsI1YBPZTn3e5kCj7A6cmgNrFmao/UkQyA== + dependencies: + bn.js "^5.1.2" + cbor "^7.0.0" + chalk "^4.1.0" + compare-versions "^3.6.0" + debug "^4.1.1" + ethereumjs-util "^7.0.3" + fp-ts "^2.7.1" + io-ts "^2.2.9" + proper-lockfile "^4.1.1" + solidity-ast "^0.4.15" + "@resolver-engine/core@^0.3.3": version "0.3.3" resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" @@ -2066,6 +2087,13 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= +cbor@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-7.0.2.tgz#9f0b74f3dfc5896775e0802e7d68f9b6af530ce3" + integrity sha512-YR6TF7LBhTqdz0vjtoY5lDnOhHXg8/mdHd2qZYQz5q8Pl7i56/ndiIGLkms1RpkFAqrT9IHGO3cjo58SfFsF2A== + dependencies: + nofilter "^2.0.0" + chai@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" @@ -2098,7 +2126,7 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== @@ -2401,6 +2429,11 @@ commander@3.0.2: resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== +compare-versions@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" + integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -4091,6 +4124,11 @@ fp-ts@^1.0.0: resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== +fp-ts@^2.7.1: + version "2.9.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.9.5.tgz#6690cd8b76b84214a38fc77cbbbd04a38f86ea90" + integrity sha512-MiHrA5teO6t8zKArE3DdMPT/Db6v2GUt5yfWnhBTrrsVfeCJUUnV6sgFvjGNBKDmEMqVwRFkEePL7wPwqrLKKA== + fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -4354,6 +4392,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== +graceful-fs@^4.2.4: + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== + growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" @@ -4720,6 +4763,11 @@ io-ts@1.10.4: dependencies: fp-ts "^1.0.0" +io-ts@^2.2.9: + version "2.2.15" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.15.tgz#0b0b19a6f8a64f4a524ad5810d56432789428128" + integrity sha512-ww2ZPrErx5pjCCI/tWRwjlEIDEndnN9kBIxAylXj+WNIH4ZVgaUqFuabGouehkRuvrmvzO5OnZmLf+o50h4izQ== + ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" @@ -6033,6 +6081,11 @@ node-gyp-build@^4.2.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.3.tgz#ce6277f853835f718829efb47db20f3e4d9c4739" integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg== +nofilter@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-2.0.0.tgz#57a2d7c6fcd34dd396f490d6942c4f58640b5823" + integrity sha512-i3ck2PUWBa+trsGGBvwS3msnTowbFei5G++BgpOpT7y7VTrprXphMQP5svTdsMLdttKDZFo+5RqVWRqhmf+BwQ== + normalize-package-data@^2.3.2: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -6590,6 +6643,15 @@ promise-to-callback@^1.0.0: is-fn "^1.0.0" set-immediate-shim "^1.0.1" +proper-lockfile@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" + integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== + dependencies: + graceful-fs "^4.2.4" + retry "^0.12.0" + signal-exit "^3.0.2" + proxy-addr@~2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" @@ -7043,6 +7105,11 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= + rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -7440,6 +7507,11 @@ solhint-plugin-prettier@^0.0.5: dependencies: prettier-linter-helpers "^1.0.0" +solidity-ast@^0.4.15: + version "0.4.17" + resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.17.tgz#e857b4f64466f3eb94da78fe961c0d256c84b228" + integrity sha512-5jkkabmjPdy9W9c2DMQBlKobVBz7KDnipxn+0zW191uD6BML3w7dQ+ihUvwA9XOm9ILDECrb5Y8z2vu47STqCg== + solidity-comments-extractor@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.4.tgz#ce420aef23641ffd0131c7d80ba85b6e1e42147e"