diff --git a/.gitignore b/.gitignore index 8b6c6ef..8737c62 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,4 @@ cache artifacts artifacts-ovm cache-ovm - +src/types diff --git a/.prettierignore b/.prettierignore index 23f9441..8d49586 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,3 +5,4 @@ artifacts-ovm cache cache-ovm contracts/Verifier*.sol +src/types \ No newline at end of file diff --git a/circuits/merkleProof.circom b/circuits/merkleProof.circom new file mode 100644 index 0000000..5c31b83 --- /dev/null +++ b/circuits/merkleProof.circom @@ -0,0 +1,30 @@ +include "../node_modules/circomlib/circuits/poseidon.circom"; +include "../node_modules/circomlib/circuits/switcher.circom"; + +// Verifies that merkle proof is correct for given merkle root and a leaf +// pathIndices bits is an array of 0/1 selectors telling whether given pathElement is on the left or right side of merkle path +template MerkleProof(levels) { + signal input leaf; + signal input pathElements[levels]; + signal input pathIndices; + signal output root; + + component switcher[levels]; + component hasher[levels]; + + component indexBits = Num2Bits(levels); + indexBits.in <== pathIndices; + + for (var i = 0; i < levels; i++) { + switcher[i] = Switcher(); + switcher[i].L <== i == 0 ? leaf : hasher[i - 1].out; + switcher[i].R <== pathElements[i]; + switcher[i].sel <== indexBits.out[i]; + + hasher[i] = Poseidon(2); + hasher[i].inputs[0] <== switcher[i].outL; + hasher[i].inputs[1] <== switcher[i].outR; + } + + root <== hasher[levels - 1].out; +} diff --git a/circuits/merkleTree.circom b/circuits/merkleTree.circom index 302c0d7..fafb746 100644 --- a/circuits/merkleTree.circom +++ b/circuits/merkleTree.circom @@ -1,54 +1,32 @@ include "../node_modules/circomlib/circuits/poseidon.circom"; -// Computes MiMC([left, right]) -template HashLeftRight() { - signal input left; - signal input right; - signal output hash; +// Helper template that computes hashes of the next tree layer +template TreeLayer(height) { + var nItems = 1 << height; + signal input ins[nItems * 2]; + signal output outs[nItems]; - component hasher = Poseidon(2); - hasher.inputs[0] <== left; - hasher.inputs[1] <== right; - hash <== hasher.out; + component hash[nItems]; + for(var i = 0; i < nItems; i++) { + hash[i] = Poseidon(2); + hash[i].inputs[0] <== ins[i * 2]; + hash[i].inputs[1] <== ins[i * 2 + 1]; + hash[i].out ==> outs[i]; + } } -// if s == 0 returns [in[0], in[1]] -// if s == 1 returns [in[1], in[0]] -template DualMux() { - signal input in[2]; - signal input s; - signal output out[2]; - - s * (1 - s) === 0 - out[0] <== (in[1] - in[0])*s + in[0]; - out[1] <== (in[0] - in[1])*s + in[1]; -} - -// Verifies that merkle proof is correct for given merkle root and a leaf -// pathIndices input is an array of 0/1 selectors telling whether given pathElement is on the left or right side of merkle path +// Builds a merkle tree from leaf array template MerkleTree(levels) { - signal input leaf; - signal input pathElements[levels]; - signal input pathIndices; + signal input leaves[1 << levels]; + signal output root; - signal output root; - - component selectors[levels]; - component hashers[levels]; - - component indexBits = Num2Bits(levels); - indexBits.in <== pathIndices; - - for (var i = 0; i < levels; i++) { - selectors[i] = DualMux(); - selectors[i].in[0] <== i == 0 ? leaf : hashers[i - 1].hash; - selectors[i].in[1] <== pathElements[i]; - selectors[i].s <== indexBits.out[i]; - - hashers[i] = HashLeftRight(); - hashers[i].left <== selectors[i].out[0]; - hashers[i].right <== selectors[i].out[1]; + component layers[levels]; + for(var level = levels - 1; level >= 0; level--) { + layers[level] = TreeLayer(level); + for(var i = 0; i < (1 << (level + 1)); i++) { + layers[level].ins[i] <== level == levels - 1 ? leaves[i] : layers[level + 1].outs[i]; } + } - root <== hashers[levels - 1].hash; -} + root <== levels > 0 ? layers[0].outs[0] : leaves[0]; +} \ No newline at end of file diff --git a/circuits/transaction.circom b/circuits/transaction.circom index db4499c..a66cc01 100644 --- a/circuits/transaction.circom +++ b/circuits/transaction.circom @@ -1,4 +1,4 @@ -include "./merkleTree.circom" +include "./merkleProof.circom" include "./treeUpdater.circom" include "./utils.circom" @@ -43,7 +43,6 @@ template Transaction(levels, nIns, nOuts, zeroLeaf) { component inKeypair[nIns]; component inUtxoHasher[nIns]; component nullifierHasher[nIns]; - component inAmountCheck[nIns]; component tree[nIns]; component checkRoot[nIns]; var sumIns = 0; @@ -64,7 +63,7 @@ template Transaction(levels, nIns, nOuts, zeroLeaf) { nullifierHasher[tx].privateKey <== inPrivateKey[tx]; nullifierHasher[tx].nullifier === inputNullifier[tx]; - tree[tx] = MerkleTree(levels); + tree[tx] = MerkleProof(levels); tree[tx].leaf <== inUtxoHasher[tx].commitment; tree[tx].pathIndices <== inPathIndices[tx]; for (var i = 0; i < levels; i++) { @@ -77,9 +76,9 @@ template Transaction(levels, nIns, nOuts, zeroLeaf) { checkRoot[tx].in[1] <== tree[tx].root; checkRoot[tx].enabled <== inAmount[tx]; - // Check that amount fits into 248 bits to prevent overflow - inAmountCheck[tx] = Num2Bits(248); - inAmountCheck[tx].in <== inAmount[tx]; + // We don't need to range check input amounts, since all inputs are valid UTXOs that + // were already checked as outputs in the previous transaction (or zero amount UTXOs that don't + // need to be checked either). sumIns += inAmount[tx]; } @@ -124,7 +123,7 @@ template Transaction(levels, nIns, nOuts, zeroLeaf) { treeUpdater.oldRoot <== root; treeUpdater.newRoot <== newRoot; for (var i = 0; i < nOuts; i++) { - treeUpdater.leaf[i] <== outputCommitment[i]; + treeUpdater.leaves[i] <== outputCommitment[i]; } treeUpdater.pathIndices <== outPathIndices; for (var i = 0; i < levels - 1; i++) { diff --git a/circuits/treeUpdater.circom b/circuits/treeUpdater.circom index c77ae7a..63de031 100644 --- a/circuits/treeUpdater.circom +++ b/circuits/treeUpdater.circom @@ -1,27 +1,25 @@ +include "./merkleProof.circom"; include "./merkleTree.circom"; // inserts a subtree into a merkle tree // checks that tree previously contained zeroes is the same positions // zeroSubtreeRoot is a root of a subtree that contains only zeroes template TreeUpdater(levels, subtreeLevels, zeroSubtreeRoot) { - // currently it works only with 1-level subtrees - assert(subtreeLevels == 1); var remainingLevels = levels - subtreeLevels; signal input oldRoot; signal input newRoot; - signal input leaf[1 << subtreeLevels]; + signal input leaves[1 << subtreeLevels]; signal input pathIndices; signal private input pathElements[remainingLevels]; // calculate subtree root - // todo: make it work with arbitrary subtree levels - // currently it works only with 1-level subtrees - component leafPair = HashLeftRight(); - leafPair.left <== leaf[0]; - leafPair.right <== leaf[1]; + component subtree = MerkleTree(subtreeLevels); + for(var i = 0; i < (1 << subtreeLevels); i++) { + subtree.leaves[i] <== leaves[i]; + } - component treeBefore = MerkleTree(remainingLevels); + component treeBefore = MerkleProof(remainingLevels); for(var i = 0; i < remainingLevels; i++) { treeBefore.pathElements[i] <== pathElements[i]; } @@ -29,11 +27,11 @@ template TreeUpdater(levels, subtreeLevels, zeroSubtreeRoot) { treeBefore.leaf <== zeroSubtreeRoot; treeBefore.root === oldRoot; - component treeAfter = MerkleTree(remainingLevels); + component treeAfter = MerkleProof(remainingLevels); for(var i = 0; i < remainingLevels; i++) { treeAfter.pathElements[i] <== pathElements[i]; } treeAfter.pathIndices <== pathIndices; - treeAfter.leaf <== leafPair.hash; + treeAfter.leaf <== subtree.root; treeAfter.root === newRoot; } diff --git a/circuits/utils.circom b/circuits/utils.circom index d7ce7df..a32ccfb 100644 --- a/circuits/utils.circom +++ b/circuits/utils.circom @@ -16,7 +16,6 @@ template TransactionHasher() { signal input amount; signal input blinding; signal input publicKey; - signal output commitment; component hasher = Poseidon(3); @@ -27,10 +26,9 @@ template TransactionHasher() { } template NullifierHasher() { - signal input privateKey; - signal input merklePath; signal input commitment; - + signal input merklePath; + signal input privateKey; signal output nullifier; component hasher = Poseidon(3); diff --git a/hardhat.config.js b/hardhat.config.js index deb6563..7978e67 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -1,4 +1,6 @@ /* eslint-disable indent */ +require('@typechain/hardhat') +require('@nomiclabs/hardhat-ethers') require('@nomiclabs/hardhat-waffle') require('@eth-optimism/hardhat-ovm') require('dotenv').config() @@ -42,6 +44,9 @@ const config = { mocha: { timeout: 600000000, }, + typechain: { + outDir: 'src/types', + }, } module.exports = config diff --git a/package.json b/package.json index 3b2ea75..5cdc8d6 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,8 @@ "@nomiclabs/hardhat-waffle": "^2.0.1", "@openzeppelin/contracts": "git+https://github.com/tornadocash/openzeppelin-contracts.git#6e46aa6946a7f215e7604169ddf46e1aebea850f", "@openzeppelin/contracts-upgradeable": "3.4.1", + "@typechain/ethers-v5": "^7.0.1", + "@typechain/hardhat": "^2.3.0", "bignumber.js": "^9.0.0", "chai": "^4.3.4", "circom": "^0.5.45", @@ -39,8 +41,10 @@ "ffjavascript": "^0.2.36", "fixed-merkle-tree": "^0.5.1", "hardhat": "^2.3.0", + "mocha": "^9.1.0", "snarkjs": "git+https://github.com/tornadocash/snarkjs.git#616c2d30699f28c8f3ab737b877402ccbb604cfe", - "tmp-promise": "^3.0.2" + "tmp-promise": "^3.0.2", + "typechain": "^5.1.2" }, "devDependencies": { "@eth-optimism/hardhat-ovm": "^0.2.2", diff --git a/src/utils.js b/src/utils.js index a214fee..c9ac1fe 100644 --- a/src/utils.js +++ b/src/utils.js @@ -76,13 +76,6 @@ function shuffle(array) { return array } -async function takeSnapshot() { - return await ethers.provider.send('evm_snapshot', []) -} - -async function revertSnapshot(id) { - await ethers.provider.send('evm_revert', [id]) -} async function getSignerFromAddress(address) { await network.provider.request({ @@ -101,8 +94,6 @@ module.exports = { poseidonHash, poseidonHash2, getExtDataHash, - takeSnapshot, - revertSnapshot, shuffle, getSignerFromAddress, } diff --git a/test/.mocharc.json b/test/.mocharc.json new file mode 100644 index 0000000..2abd065 --- /dev/null +++ b/test/.mocharc.json @@ -0,0 +1,4 @@ +{ + "require": "hardhat/register", + "timeout": 20000 +} diff --git a/test/full.test.js b/test/full.test.js index 4e3168c..6d1a980 100644 --- a/test/full.test.js +++ b/test/full.test.js @@ -1,8 +1,9 @@ -/* global ethers */ -const { expect, should } = require('chai') -should() +const hre = require('hardhat') +const { ethers, waffle } = hre +const { loadFixture } = waffle +const { expect } = require('chai') -const { poseidonHash2, toFixedHex, takeSnapshot, revertSnapshot } = require('../src/utils') +const { poseidonHash2, toFixedHex } = require('../src/utils') const Utxo = require('../src/utxo') const MERKLE_TREE_HEIGHT = 5 @@ -11,20 +12,20 @@ const MerkleTree = require('fixed-merkle-tree') const { transaction, registerAndTransact } = require('../src/index') const { Keypair } = require('../src/keypair') -describe('TornadoPool', () => { - let snapshotId, tornadoPool, sender, gov, proxy, messenger +describe('TornadoPool', function () { + this.timeout(20000) + let tornadoPool, sender, gov, messenger - /* prettier-ignore */ - before(async function () { + async function deploy(contractName, ...args) { + const Factory = await ethers.getContractFactory(contractName) + const instance = await Factory.deploy(...args) + return instance.deployed() + } + + async function fixture() { ;[sender, gov] = await ethers.getSigners() - - const Verifier2 = await ethers.getContractFactory('Verifier2') - const verifier2 = await Verifier2.deploy() - await verifier2.deployed() - - const Verifier16 = await ethers.getContractFactory('Verifier16') - const verifier16 = await Verifier16.deploy() - await verifier16.deployed() + const verifier2 = await deploy('Verifier2') + const verifier16 = await deploy('Verifier16') const tree = new MerkleTree(MERKLE_TREE_HEIGHT, [], { hashFunction: poseidonHash2 }) const root = await tree.root() @@ -37,16 +38,29 @@ describe('TornadoPool', () => { await messenger.deployed() const CrossChainUpgradeableProxy = await ethers.getContractFactory('CrossChainUpgradeableProxy') - proxy = await CrossChainUpgradeableProxy.deploy(tornadoPoolImpl.address, gov.address, [], messenger.address) + proxy = await CrossChainUpgradeableProxy.deploy( + tornadoPoolImpl.address, + gov.address, + [], + messenger.address, + ) await proxy.deployed() - tornadoPool = await Pool.attach(proxy.address) + /** @type {TornadoPool} */ + tornadoPool = Pool.attach(proxy.address) await tornadoPool.initialize(toFixedHex(root)) + return { tornadoPool } + } - snapshotId = await takeSnapshot() - }) describe('Upgradeability tests', () => { + let tornadoPool, proxy + before(async () => { + ;({ tornadoPool } = await loadFixture(fixture)) + const CrossChainUpgradeableProxy = await ethers.getContractFactory('CrossChainUpgradeableProxy') + proxy = CrossChainUpgradeableProxy.attach(tornadoPool.address) + }) + it('admin should be gov', async () => { const { data } = await proxy.populateTransaction.admin() const { result } = await messenger.callStatic.execute(proxy.address, data) @@ -54,11 +68,9 @@ describe('TornadoPool', () => { }) it('non admin cannot call', async () => { - await proxy - .admin() - .should.be.revertedWith( - "Transaction reverted: function selector was not recognized and there's no fallback function", - ) + await expect(proxy.admin()).to.be.revertedWith( + "Transaction reverted: function selector was not recognized and there's no fallback function", + ) }) }) @@ -72,6 +84,7 @@ describe('TornadoPool', () => { }) it('constants check', async () => { + const { tornadoPool } = await loadFixture(fixture) const maxFee = await tornadoPool.MAX_FEE() const maxExtAmount = await tornadoPool.MAX_EXT_AMOUNT() const fieldSize = await tornadoPool.FIELD_SIZE() @@ -80,6 +93,9 @@ describe('TornadoPool', () => { }) it('should register and deposit', async function () { + let { tornadoPool } = await loadFixture(fixture) + const sender = (await ethers.getSigners())[0] + // Alice deposits into tornado pool const aliceDepositAmount = 1e7 const aliceDepositUtxo = new Utxo({ amount: aliceDepositAmount }) @@ -138,6 +154,8 @@ describe('TornadoPool', () => { }) it('should deposit, transact and withdraw', async function () { + const { tornadoPool } = await loadFixture(fixture) + // Alice deposits into tornado pool const aliceDepositAmount = 1e7 const aliceDepositUtxo = new Utxo({ amount: aliceDepositAmount }) @@ -185,11 +203,7 @@ describe('TornadoPool', () => { }) it('should work with 16 inputs', async function () { + const { tornadoPool } = await loadFixture(fixture) await transaction({ tornadoPool, inputs: [new Utxo(), new Utxo(), new Utxo()] }) }) - - afterEach(async () => { - await revertSnapshot(snapshotId) - snapshotId = await takeSnapshot() - }) }) diff --git a/yarn.lock b/yarn.lock index 45eac26..4e2bae2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -835,6 +835,18 @@ dependencies: ethers "^5.0.2" +"@typechain/ethers-v5@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-7.0.1.tgz#f9ae60ae5bd9e8ea8a996f66244147e8e74034ae" + integrity sha512-mXEJ7LG0pOYO+MRPkHtbf30Ey9X2KAsU0wkeoVvjQIn7iAY6tB3k3s+82bbmJAUMyENbQ04RDOZit36CgSG6Gg== + +"@typechain/hardhat@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-2.3.0.tgz#dc7f29281637b38b77c7c046ae82700703395d0f" + integrity sha512-zERrtNol86L4DX60ktnXxP7Cq8rSZHPaQvsChyiQQVuvVs2FTLm24Yi+MYnfsIdbUBIXZG7SxDWhtCF5I0tJNQ== + dependencies: + fs-extra "^9.1.0" + "@types/abstract-leveldown@*": version "5.0.2" resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-5.0.2.tgz#ee81917fe38f770e29eec8139b6f16ee4a8b0a5f" @@ -1297,6 +1309,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -2283,7 +2300,7 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1, 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.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2338,7 +2355,7 @@ chokidar@3.5.1: optionalDependencies: fsevents "~2.3.1" -chokidar@^3.4.0: +chokidar@3.5.2, chokidar@^3.4.0: version "3.5.2" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== @@ -4431,6 +4448,16 @@ fs-extra@^7.0.0, fs-extra@^7.0.1: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-minipass@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" @@ -4586,7 +4613,7 @@ glob@7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.2, glob@^7.1.3, glob@~7.1.7: +glob@7.1.7, glob@^7.1.2, glob@^7.1.3, glob@^7.1.6, glob@~7.1.7: version "7.1.7" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== @@ -4660,7 +4687,7 @@ got@^7.1.0: url-parse-lax "^1.0.0" url-to-options "^1.0.1" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: version "4.2.8" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== @@ -5336,6 +5363,11 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + is-url@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" @@ -5443,6 +5475,13 @@ js-yaml@4.0.0: dependencies: argparse "^2.0.1" +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + js-yaml@^3.13.0, js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -5551,6 +5590,15 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -5941,6 +5989,14 @@ log-symbols@4.0.0: dependencies: chalk "^4.0.0" +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + logplease@^1.2.15: version "1.2.15" resolved "https://registry.yarnpkg.com/logplease/-/logplease-1.2.15.tgz#3da442e93751a5992cc19010a826b08d0293c48a" @@ -6275,7 +6331,7 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*: +mkdirp@*, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -6355,6 +6411,37 @@ mocha@^8.2.1: yargs-parser "20.2.4" yargs-unparser "2.0.0" +mocha@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.1.0.tgz#0a7aa6fc4f59d1015d4e11747d9104b752553c67" + integrity sha512-Kjg/XxYOFFUi0h/FwMOeb6RoroiZ+P1yOfya6NK7h3dNhahrJx1r2XIT3ge4ZQvJM86mdjNA+W5phqRQh7DwCg== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.2" + debug "4.3.1" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.1.7" + growl "1.10.5" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "3.0.4" + ms "2.1.3" + nanoid "3.1.23" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + wide-align "1.1.3" + workerpool "6.1.5" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + mock-fs@^4.1.0: version "4.14.0" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" @@ -6445,6 +6532,11 @@ nanoid@3.1.20: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw== +nanoid@3.1.23: + version "3.1.23" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" + integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -7733,6 +7825,13 @@ serialize-javascript@5.0.1: dependencies: randombytes "^2.1.0" +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + serve-static@1.14.1: version "1.14.1" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" @@ -8513,6 +8612,11 @@ ts-essentials@^6.0.3: resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.7.tgz#5f4880911b7581a873783740ce8b94da163d18a6" integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== +ts-essentials@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== + ts-generator@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" @@ -8625,6 +8729,22 @@ typechain@^3.0.0: ts-essentials "^6.0.3" ts-generator "^0.1.1" +typechain@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-5.1.2.tgz#c8784d6155a8e69397ca47f438a3b4fb2aa939da" + integrity sha512-FuaCxJd7BD3ZAjVJoO+D6TnqKey3pQdsqOBsC83RKYWKli5BDhdf0TPkwfyjt20TUlZvOzJifz+lDwXsRkiSKA== + dependencies: + "@types/prettier" "^2.1.1" + command-line-args "^4.0.7" + debug "^4.1.1" + fs-extra "^7.0.0" + glob "^7.1.6" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.1.2" + ts-essentials "^7.0.1" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -8699,6 +8819,11 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + unorm@^1.3.3: version "1.6.0" resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" @@ -9486,6 +9611,11 @@ workerpool@6.1.0: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.0.tgz#a8e038b4c94569596852de7a8ea4228eefdeb37b" integrity sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg== +workerpool@6.1.5: + version "6.1.5" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.5.tgz#0f7cf076b6215fd7e1da903ff6f22ddd1886b581" + integrity sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw== + wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"