mirror of
https://github.com/tornadocash/tornado-core.git
synced 2024-12-17 23:03:30 +01:00
lint
This commit is contained in:
parent
c6b442713a
commit
346ffcee3c
27
.eslintrc
Normal file
27
.eslintrc
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"mocha": true
|
||||
},
|
||||
"extends": ["eslint:recommended", "plugin:prettier/recommended", "prettier"],
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
"rules": {
|
||||
"indent": ["error", 2],
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"quotes": ["error", "single"],
|
||||
"semi": ["error", "never"],
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"require-await": "error",
|
||||
"prettier/prettier": ["error", { "printWidth": 110 }]
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"mocha": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
"rules": {
|
||||
"indent": [
|
||||
"error",
|
||||
2
|
||||
],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
],
|
||||
"semi": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"object-curly-spacing": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"require-await": "error"
|
||||
}
|
||||
}
|
6
.prettierignore
Normal file
6
.prettierignore
Normal file
@ -0,0 +1,6 @@
|
||||
.vscode
|
||||
build
|
||||
circuits
|
||||
contracts/Verifier.sol
|
||||
lib/ganacheHelper.js
|
||||
cli.js
|
16
.prettierrc
Normal file
16
.prettierrc
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"bracketSpacing": true,
|
||||
"semi": false,
|
||||
"printWidth": 110,
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.sol",
|
||||
"options": {
|
||||
"singleQuote": false,
|
||||
"printWidth": 130
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,6 +1,13 @@
|
||||
{
|
||||
"extends": "solhint:recommended",
|
||||
"rules": {
|
||||
"indent": ["error", 2]
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
"printWidth": 110
|
||||
}
|
||||
],
|
||||
"quotes": ["error", "double"]
|
||||
},
|
||||
"plugins": ["prettier"]
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
dist: trusty
|
||||
language: node_js
|
||||
node_js:
|
||||
- "11"
|
||||
- '11'
|
||||
install:
|
||||
- npm ci
|
||||
- cp .env.example .env
|
||||
|
16
cli.js
16
cli.js
@ -178,7 +178,7 @@ async function generateProof({ deposit, recipient, relayerAddress = 0, fee = 0,
|
||||
toHex(input.recipient, 20),
|
||||
toHex(input.relayer, 20),
|
||||
toHex(input.fee),
|
||||
toHex(input.refund)
|
||||
toHex(input.refund),
|
||||
]
|
||||
|
||||
return { proof, args }
|
||||
@ -265,7 +265,7 @@ function fromDecimals({ amount, decimals }) {
|
||||
const comps = ether.split('.')
|
||||
if (comps.length > 2) {
|
||||
throw new Error(
|
||||
'[ethjs-unit] while converting number ' + amount + ' to wei, too many decimal points'
|
||||
'[ethjs-unit] while converting number ' + amount + ' to wei, too many decimal points',
|
||||
)
|
||||
}
|
||||
|
||||
@ -280,7 +280,7 @@ function fromDecimals({ amount, decimals }) {
|
||||
}
|
||||
if (fraction.length > baseLength) {
|
||||
throw new Error(
|
||||
'[ethjs-unit] while converting number ' + amount + ' to wei, too many decimal places'
|
||||
'[ethjs-unit] while converting number ' + amount + ' to wei, too many decimal places',
|
||||
)
|
||||
}
|
||||
|
||||
@ -417,10 +417,10 @@ async function loadDepositData({ deposit }) {
|
||||
try {
|
||||
const eventWhenHappened = await tornado.getPastEvents('Deposit', {
|
||||
filter: {
|
||||
commitment: deposit.commitmentHex
|
||||
commitment: deposit.commitmentHex,
|
||||
},
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
toBlock: 'latest',
|
||||
})
|
||||
if (eventWhenHappened.length === 0) {
|
||||
throw new Error('There is no related deposit, the note is invalid')
|
||||
@ -441,7 +441,7 @@ async function loadWithdrawalData({ amount, currency, deposit }) {
|
||||
try {
|
||||
const events = await await tornado.getPastEvents('Withdrawal', {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
toBlock: 'latest',
|
||||
})
|
||||
|
||||
const withdrawEvent = events.filter((event) => {
|
||||
@ -451,7 +451,7 @@ async function loadWithdrawalData({ amount, currency, deposit }) {
|
||||
const fee = withdrawEvent.returnValues.fee
|
||||
const decimals = config.deployments[`netId${netId}`][currency].decimals
|
||||
const withdrawalAmount = toBN(fromDecimals({ amount, decimals })).sub(
|
||||
toBN(fee)
|
||||
toBN(fee),
|
||||
)
|
||||
const { timestamp } = await web3.eth.getBlock(withdrawEvent.blockHash)
|
||||
return {
|
||||
@ -460,7 +460,7 @@ async function loadWithdrawalData({ amount, currency, deposit }) {
|
||||
to: withdrawEvent.returnValues.to,
|
||||
timestamp,
|
||||
nullifier: deposit.nullifierHex,
|
||||
fee: toDecimals(fee, decimals, 9)
|
||||
fee: toDecimals(fee, decimals, 9),
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('loadWithdrawalData', e)
|
||||
|
@ -8,11 +8,11 @@ const genContract = require('circomlib/src/mimcsponge_gencontract.js')
|
||||
// command
|
||||
const outputPath = path.join(__dirname, 'build', 'Hasher.json')
|
||||
|
||||
function main () {
|
||||
function main() {
|
||||
const contract = {
|
||||
contractName: 'Hasher',
|
||||
abi: genContract.abi,
|
||||
bytecode: genContract.createCode('mimcsponge', 220)
|
||||
bytecode: genContract.createCode('mimcsponge', 220),
|
||||
}
|
||||
|
||||
fs.writeFileSync(outputPath, JSON.stringify(contract))
|
||||
|
128
config.js
128
config.js
@ -5,136 +5,136 @@ module.exports = {
|
||||
netId1: {
|
||||
eth: {
|
||||
instanceAddress: {
|
||||
'0.1': '0x12D66f87A04A9E220743712cE6d9bB1B5616B8Fc',
|
||||
'1': '0x47CE0C6eD5B0Ce3d3A51fdb1C52DC66a7c3c2936',
|
||||
'10': '0x910Cbd523D972eb0a6f4cAe4618aD62622b39DbF',
|
||||
'100': '0xA160cdAB225685dA1d56aa342Ad8841c3b53f291'
|
||||
0.1: '0x12D66f87A04A9E220743712cE6d9bB1B5616B8Fc',
|
||||
1: '0x47CE0C6eD5B0Ce3d3A51fdb1C52DC66a7c3c2936',
|
||||
10: '0x910Cbd523D972eb0a6f4cAe4618aD62622b39DbF',
|
||||
100: '0xA160cdAB225685dA1d56aa342Ad8841c3b53f291',
|
||||
},
|
||||
symbol: 'ETH',
|
||||
decimals: 18
|
||||
decimals: 18,
|
||||
},
|
||||
dai: {
|
||||
instanceAddress: {
|
||||
'100': '0xD4B88Df4D29F5CedD6857912842cff3b20C8Cfa3',
|
||||
'1000': '0xFD8610d20aA15b7B2E3Be39B396a1bC3516c7144',
|
||||
'10000': '0xF60dD140cFf0706bAE9Cd734Ac3ae76AD9eBC32A',
|
||||
'100000': undefined
|
||||
100: '0xD4B88Df4D29F5CedD6857912842cff3b20C8Cfa3',
|
||||
1000: '0xFD8610d20aA15b7B2E3Be39B396a1bC3516c7144',
|
||||
10000: '0xF60dD140cFf0706bAE9Cd734Ac3ae76AD9eBC32A',
|
||||
100000: undefined,
|
||||
},
|
||||
tokenAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
|
||||
symbol: 'DAI',
|
||||
decimals: 18
|
||||
decimals: 18,
|
||||
},
|
||||
cdai: {
|
||||
instanceAddress: {
|
||||
'5000': '0x22aaA7720ddd5388A3c0A3333430953C68f1849b',
|
||||
'50000': '0xBA214C1c1928a32Bffe790263E38B4Af9bFCD659',
|
||||
'500000': '0xb1C8094B234DcE6e03f10a5b673c1d8C69739A00',
|
||||
'5000000': undefined
|
||||
5000: '0x22aaA7720ddd5388A3c0A3333430953C68f1849b',
|
||||
50000: '0xBA214C1c1928a32Bffe790263E38B4Af9bFCD659',
|
||||
500000: '0xb1C8094B234DcE6e03f10a5b673c1d8C69739A00',
|
||||
5000000: undefined,
|
||||
},
|
||||
tokenAddress: '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643',
|
||||
symbol: 'cDAI',
|
||||
decimals: 8
|
||||
decimals: 8,
|
||||
},
|
||||
usdc: {
|
||||
instanceAddress: {
|
||||
'100': '0xd96f2B1c14Db8458374d9Aca76E26c3D18364307',
|
||||
'1000': '0x4736dCf1b7A3d580672CcE6E7c65cd5cc9cFBa9D',
|
||||
'10000': '0xD691F27f38B395864Ea86CfC7253969B409c362d',
|
||||
'100000': undefined
|
||||
100: '0xd96f2B1c14Db8458374d9Aca76E26c3D18364307',
|
||||
1000: '0x4736dCf1b7A3d580672CcE6E7c65cd5cc9cFBa9D',
|
||||
10000: '0xD691F27f38B395864Ea86CfC7253969B409c362d',
|
||||
100000: undefined,
|
||||
},
|
||||
tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
|
||||
symbol: 'USDC',
|
||||
decimals: 6
|
||||
decimals: 6,
|
||||
},
|
||||
cusdc: {
|
||||
instanceAddress: {
|
||||
'5000': '0xaEaaC358560e11f52454D997AAFF2c5731B6f8a6',
|
||||
'50000': '0x1356c899D8C9467C7f71C195612F8A395aBf2f0a',
|
||||
'500000': '0xA60C772958a3eD56c1F15dD055bA37AC8e523a0D',
|
||||
'5000000': undefined
|
||||
5000: '0xaEaaC358560e11f52454D997AAFF2c5731B6f8a6',
|
||||
50000: '0x1356c899D8C9467C7f71C195612F8A395aBf2f0a',
|
||||
500000: '0xA60C772958a3eD56c1F15dD055bA37AC8e523a0D',
|
||||
5000000: undefined,
|
||||
},
|
||||
tokenAddress: '0x39AA39c021dfbaE8faC545936693aC917d5E7563',
|
||||
symbol: 'cUSDC',
|
||||
decimals: 8
|
||||
decimals: 8,
|
||||
},
|
||||
usdt: {
|
||||
instanceAddress: {
|
||||
'100': '0x169AD27A470D064DEDE56a2D3ff727986b15D52B',
|
||||
'1000': '0x0836222F2B2B24A3F36f98668Ed8F0B38D1a872f',
|
||||
'10000': '0xF67721A2D8F736E75a49FdD7FAd2e31D8676542a',
|
||||
'100000': '0x9AD122c22B14202B4490eDAf288FDb3C7cb3ff5E'
|
||||
100: '0x169AD27A470D064DEDE56a2D3ff727986b15D52B',
|
||||
1000: '0x0836222F2B2B24A3F36f98668Ed8F0B38D1a872f',
|
||||
10000: '0xF67721A2D8F736E75a49FdD7FAd2e31D8676542a',
|
||||
100000: '0x9AD122c22B14202B4490eDAf288FDb3C7cb3ff5E',
|
||||
},
|
||||
tokenAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
|
||||
symbol: 'USDT',
|
||||
decimals: 6
|
||||
}
|
||||
decimals: 6,
|
||||
},
|
||||
},
|
||||
netId42: {
|
||||
eth: {
|
||||
instanceAddress: {
|
||||
'0.1': '0x8b3f5393bA08c24cc7ff5A66a832562aAB7bC95f',
|
||||
'1': '0xD6a6AC46d02253c938B96D12BE439F570227aE8E',
|
||||
'10': '0xe1BE96331391E519471100c3c1528B66B8F4e5a7',
|
||||
'100': '0xd037E0Ac98Dab2fCb7E296c69C6e52767Ae5414D'
|
||||
0.1: '0x8b3f5393bA08c24cc7ff5A66a832562aAB7bC95f',
|
||||
1: '0xD6a6AC46d02253c938B96D12BE439F570227aE8E',
|
||||
10: '0xe1BE96331391E519471100c3c1528B66B8F4e5a7',
|
||||
100: '0xd037E0Ac98Dab2fCb7E296c69C6e52767Ae5414D',
|
||||
},
|
||||
symbol: 'ETH',
|
||||
decimals: 18
|
||||
decimals: 18,
|
||||
},
|
||||
dai: {
|
||||
instanceAddress: {
|
||||
'100': '0xdf2d3cC5F361CF95b3f62c4bB66deFe3FDE47e3D',
|
||||
'1000': '0xD96291dFa35d180a71964D0894a1Ae54247C4ccD',
|
||||
'10000': '0xb192794f72EA45e33C3DF6fe212B9c18f6F45AE3',
|
||||
'100000': undefined
|
||||
100: '0xdf2d3cC5F361CF95b3f62c4bB66deFe3FDE47e3D',
|
||||
1000: '0xD96291dFa35d180a71964D0894a1Ae54247C4ccD',
|
||||
10000: '0xb192794f72EA45e33C3DF6fe212B9c18f6F45AE3',
|
||||
100000: undefined,
|
||||
},
|
||||
tokenAddress: '0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa',
|
||||
symbol: 'DAI',
|
||||
decimals: 18
|
||||
decimals: 18,
|
||||
},
|
||||
cdai: {
|
||||
instanceAddress: {
|
||||
'5000': '0x6Fc9386ABAf83147b3a89C36D422c625F44121C8',
|
||||
'50000': '0x7182EA067e0f050997444FCb065985Fd677C16b6',
|
||||
'500000': '0xC22ceFd90fbd1FdEeE554AE6Cc671179BC3b10Ae',
|
||||
'5000000': undefined
|
||||
5000: '0x6Fc9386ABAf83147b3a89C36D422c625F44121C8',
|
||||
50000: '0x7182EA067e0f050997444FCb065985Fd677C16b6',
|
||||
500000: '0xC22ceFd90fbd1FdEeE554AE6Cc671179BC3b10Ae',
|
||||
5000000: undefined,
|
||||
},
|
||||
tokenAddress: '0xe7bc397DBd069fC7d0109C0636d06888bb50668c',
|
||||
symbol: 'cDAI',
|
||||
decimals: 8
|
||||
decimals: 8,
|
||||
},
|
||||
usdc: {
|
||||
instanceAddress: {
|
||||
'100': '0x137E2B6d185018e7f09f6cf175a970e7fC73826C',
|
||||
'1000': '0xcC7f1633A5068E86E3830e692e3e3f8f520525Af',
|
||||
'10000': '0x28C8f149a0ab8A9bdB006B8F984fFFCCE52ef5EF',
|
||||
'100000': undefined
|
||||
100: '0x137E2B6d185018e7f09f6cf175a970e7fC73826C',
|
||||
1000: '0xcC7f1633A5068E86E3830e692e3e3f8f520525Af',
|
||||
10000: '0x28C8f149a0ab8A9bdB006B8F984fFFCCE52ef5EF',
|
||||
100000: undefined,
|
||||
},
|
||||
tokenAddress: '0x75B0622Cec14130172EaE9Cf166B92E5C112FaFF',
|
||||
symbol: 'USDC',
|
||||
decimals: 6
|
||||
decimals: 6,
|
||||
},
|
||||
cusdc: {
|
||||
instanceAddress: {
|
||||
'5000': '0xc0648F28ABA385c8a1421Bbf1B59e3c474F89cB0',
|
||||
'50000': '0x0C53853379c6b1A7B74E0A324AcbDD5Eabd4981D',
|
||||
'500000': '0xf84016A0E03917cBe700D318EB1b7a53e6e3dEe1',
|
||||
'5000000': undefined
|
||||
5000: '0xc0648F28ABA385c8a1421Bbf1B59e3c474F89cB0',
|
||||
50000: '0x0C53853379c6b1A7B74E0A324AcbDD5Eabd4981D',
|
||||
500000: '0xf84016A0E03917cBe700D318EB1b7a53e6e3dEe1',
|
||||
5000000: undefined,
|
||||
},
|
||||
tokenAddress: '0xcfC9bB230F00bFFDB560fCe2428b4E05F3442E35',
|
||||
symbol: 'cUSDC',
|
||||
decimals: 8
|
||||
decimals: 8,
|
||||
},
|
||||
usdt: {
|
||||
instanceAddress: {
|
||||
'100': '0x327853Da7916a6A0935563FB1919A48843036b42',
|
||||
'1000': '0x531AA4DF5858EA1d0031Dad16e3274609DE5AcC0',
|
||||
'10000': '0x0958275F0362cf6f07D21373aEE0cf37dFe415dD',
|
||||
'100000': '0x14aEd24B67EaF3FF28503eB92aeb217C47514364'
|
||||
100: '0x327853Da7916a6A0935563FB1919A48843036b42',
|
||||
1000: '0x531AA4DF5858EA1d0031Dad16e3274609DE5AcC0',
|
||||
10000: '0x0958275F0362cf6f07D21373aEE0cf37dFe415dD',
|
||||
100000: '0x14aEd24B67EaF3FF28503eB92aeb217C47514364',
|
||||
},
|
||||
tokenAddress: '0x03c5F29e9296006876d8DF210BCFfD7EA5Db1Cf1',
|
||||
symbol: 'USDT',
|
||||
decimals: 6
|
||||
}
|
||||
}
|
||||
}
|
||||
decimals: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
// 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
|
||||
*/
|
||||
* 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
|
||||
*/
|
||||
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.6.0;
|
||||
@ -23,7 +23,7 @@ contract ERC20Tornado is Tornado {
|
||||
uint256 _denomination,
|
||||
uint32 _merkleTreeHeight,
|
||||
address _token
|
||||
) Tornado(_verifier, _hasher, _denomination, _merkleTreeHeight) public {
|
||||
) public Tornado(_verifier, _hasher, _denomination, _merkleTreeHeight) {
|
||||
token = _token;
|
||||
}
|
||||
|
||||
@ -32,7 +32,12 @@ contract ERC20Tornado is Tornado {
|
||||
_safeErc20TransferFrom(msg.sender, address(this), denomination);
|
||||
}
|
||||
|
||||
function _processWithdraw(address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund) internal override {
|
||||
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");
|
||||
|
||||
_safeErc20Transfer(_recipient, denomination - _fee);
|
||||
@ -49,8 +54,20 @@ contract ERC20Tornado is Tornado {
|
||||
}
|
||||
}
|
||||
|
||||
function _safeErc20TransferFrom(address _from, address _to, uint256 _amount) internal {
|
||||
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd /* transferFrom */, _from, _to, _amount));
|
||||
function _safeErc20TransferFrom(
|
||||
address _from,
|
||||
address _to,
|
||||
uint256 _amount
|
||||
) internal {
|
||||
(bool success, bytes memory data) =
|
||||
token.call(
|
||||
abi.encodeWithSelector(
|
||||
0x23b872dd, /* transferFrom */
|
||||
_from,
|
||||
_to,
|
||||
_amount
|
||||
)
|
||||
);
|
||||
require(success, "not enough allowed tokens");
|
||||
|
||||
// if contract returns some data lets make sure that is `true` according to standard
|
||||
@ -62,7 +79,14 @@ contract ERC20Tornado is Tornado {
|
||||
}
|
||||
|
||||
function _safeErc20Transfer(address _to, uint256 _amount) internal {
|
||||
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb /* transfer */, _to, _amount));
|
||||
(bool success, bytes memory data) =
|
||||
token.call(
|
||||
abi.encodeWithSelector(
|
||||
0xa9059cbb, /* transfer */
|
||||
_to,
|
||||
_amount
|
||||
)
|
||||
);
|
||||
require(success, "not enough tokens");
|
||||
|
||||
// if contract returns some data lets make sure that is `true` according to standard
|
||||
|
@ -1,13 +1,13 @@
|
||||
// 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
|
||||
*/
|
||||
* 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
|
||||
*/
|
||||
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.6.0;
|
||||
@ -20,14 +20,18 @@ contract ETHTornado is Tornado {
|
||||
Hasher _hasher,
|
||||
uint256 _denomination,
|
||||
uint32 _merkleTreeHeight
|
||||
) Tornado(_verifier, _hasher, _denomination, _merkleTreeHeight) public {
|
||||
}
|
||||
) public Tornado(_verifier, _hasher, _denomination, _merkleTreeHeight) {}
|
||||
|
||||
function _processDeposit() internal override {
|
||||
require(msg.value == denomination, "Please send `mixDenomination` ETH along with transaction");
|
||||
}
|
||||
|
||||
function _processWithdraw(address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund) internal override {
|
||||
function _processWithdraw(
|
||||
address payable _recipient,
|
||||
address payable _relayer,
|
||||
uint256 _fee,
|
||||
uint256 _refund
|
||||
) internal override {
|
||||
// sanity checks
|
||||
require(msg.value == 0, "Message value is supposed to be zero for ETH instance");
|
||||
require(_refund == 0, "Refund value is supposed to be zero for ETH instance");
|
||||
|
@ -1,13 +1,13 @@
|
||||
// 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
|
||||
*/
|
||||
* 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
|
||||
*/
|
||||
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.6.0;
|
||||
@ -55,7 +55,11 @@ contract MerkleTreeWithHistory {
|
||||
/**
|
||||
@dev Hash 2 tree leaves, returns MiMC(_left, _right)
|
||||
*/
|
||||
function hashLeftRight(Hasher _hasher, bytes32 _left, bytes32 _right) public pure returns (bytes32) {
|
||||
function hashLeftRight(
|
||||
Hasher _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);
|
||||
@ -66,7 +70,7 @@ contract MerkleTreeWithHistory {
|
||||
return bytes32(R);
|
||||
}
|
||||
|
||||
function _insert(bytes32 _leaf) internal returns(uint32 index) {
|
||||
function _insert(bytes32 _leaf) internal returns (uint32 index) {
|
||||
uint32 currentIndex = nextIndex;
|
||||
require(currentIndex != uint32(2)**levels, "Merkle tree is full. No more leafs can be added");
|
||||
nextIndex += 1;
|
||||
@ -98,7 +102,7 @@ contract MerkleTreeWithHistory {
|
||||
/**
|
||||
@dev Whether the root is present in the root history
|
||||
*/
|
||||
function isKnownRoot(bytes32 _root) public view returns(bool) {
|
||||
function isKnownRoot(bytes32 _root) public view returns (bool) {
|
||||
if (_root == 0) {
|
||||
return false;
|
||||
}
|
||||
@ -118,7 +122,7 @@ contract MerkleTreeWithHistory {
|
||||
/**
|
||||
@dev Returns the last root
|
||||
*/
|
||||
function getLastRoot() public view returns(bytes32) {
|
||||
function getLastRoot() public view returns (bytes32) {
|
||||
return roots[currentRootIndex];
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,4 @@ pragma solidity ^0.6.0;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||
|
||||
contract ERC20Mock is ERC20 {
|
||||
constructor() ERC20("DAIMock", "DAIM") public {
|
||||
}
|
||||
}
|
||||
contract ERC20Mock is ERC20("DAIMock", "DAIM") {}
|
||||
|
@ -3,11 +3,15 @@
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
interface ERC20Basic {
|
||||
function _totalSupply() external returns(uint);
|
||||
function totalSupply() external view returns (uint);
|
||||
function balanceOf(address who) external view returns (uint);
|
||||
function transfer(address to, uint value) external;
|
||||
event Transfer(address indexed from, address indexed to, uint value);
|
||||
function _totalSupply() external returns (uint256);
|
||||
|
||||
function totalSupply() external view returns (uint256);
|
||||
|
||||
function balanceOf(address who) external view returns (uint256);
|
||||
|
||||
function transfer(address to, uint256 value) external;
|
||||
|
||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -15,8 +19,15 @@ interface ERC20Basic {
|
||||
* @dev see https://github.com/ethereum/EIPs/issues/20
|
||||
*/
|
||||
interface IUSDT is ERC20Basic {
|
||||
function allowance(address owner, address spender) external view returns (uint);
|
||||
function transferFrom(address from, address to, uint value) external;
|
||||
function approve(address spender, uint value) external;
|
||||
event Approval(address indexed owner, address indexed spender, uint value);
|
||||
function allowance(address owner, address spender) external view returns (uint256);
|
||||
|
||||
function transferFrom(
|
||||
address from,
|
||||
address to,
|
||||
uint256 value
|
||||
) external;
|
||||
|
||||
function approve(address spender, uint256 value) external;
|
||||
|
||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import '../MerkleTreeWithHistory.sol';
|
||||
import "../MerkleTreeWithHistory.sol";
|
||||
|
||||
contract MerkleTreeWithHistoryMock is MerkleTreeWithHistory {
|
||||
|
||||
constructor (uint32 _treeLevels, Hasher _hasher) MerkleTreeWithHistory(_treeLevels, _hasher) public {}
|
||||
constructor(uint32 _treeLevels, Hasher _hasher) public MerkleTreeWithHistory(_treeLevels, _hasher) {}
|
||||
|
||||
function insert(bytes32 _leaf) public {
|
||||
_insert(_leaf);
|
||||
|
@ -1,13 +1,13 @@
|
||||
// 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
|
||||
*/
|
||||
* 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
|
||||
*/
|
||||
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.6.0;
|
||||
@ -16,7 +16,7 @@ import "./MerkleTreeWithHistory.sol";
|
||||
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
||||
|
||||
interface IVerifier {
|
||||
function verifyProof(bytes memory _proof, uint256[6] memory _input) external returns(bool);
|
||||
function verifyProof(bytes memory _proof, uint256[6] memory _input) external returns (bool);
|
||||
}
|
||||
|
||||
abstract contract Tornado is MerkleTreeWithHistory, ReentrancyGuard {
|
||||
@ -49,7 +49,7 @@ abstract contract Tornado is MerkleTreeWithHistory, ReentrancyGuard {
|
||||
Hasher _hasher,
|
||||
uint256 _denomination,
|
||||
uint32 _merkleTreeHeight
|
||||
) MerkleTreeWithHistory(_merkleTreeHeight, _hasher) public {
|
||||
) public MerkleTreeWithHistory(_merkleTreeHeight, _hasher) {
|
||||
require(_denomination > 0, "denomination should be greater than 0");
|
||||
verifier = _verifier;
|
||||
denomination = _denomination;
|
||||
@ -80,11 +80,25 @@ abstract contract Tornado is MerkleTreeWithHistory, ReentrancyGuard {
|
||||
- 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 {
|
||||
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");
|
||||
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);
|
||||
@ -92,21 +106,25 @@ abstract contract Tornado is MerkleTreeWithHistory, ReentrancyGuard {
|
||||
}
|
||||
|
||||
/** @dev this function is defined in a child contract */
|
||||
function _processWithdraw(address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund) internal virtual;
|
||||
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) {
|
||||
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) {
|
||||
function isSpentArray(bytes32[] calldata _nullifierHashes) external view returns (bool[] memory spent) {
|
||||
spent = new bool[](_nullifierHashes.length);
|
||||
for(uint i = 0; i < _nullifierHashes.length; i++) {
|
||||
for (uint256 i = 0; i < _nullifierHashes.length; i++) {
|
||||
if (isSpent(_nullifierHashes[i])) {
|
||||
spent[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ async function downloadFile({ url, path }) {
|
||||
const response = await axios({
|
||||
url,
|
||||
method: 'GET',
|
||||
responseType: 'stream'
|
||||
responseType: 'stream',
|
||||
})
|
||||
|
||||
response.data.pipe(writer)
|
||||
@ -25,16 +25,16 @@ async function downloadFile({ url, path }) {
|
||||
async function main() {
|
||||
const release = await axios.get('https://api.github.com/repos/tornadocash/tornado-core/releases/latest')
|
||||
const { assets } = release.data
|
||||
if (!fs.existsSync(circuitsPath)){
|
||||
if (!fs.existsSync(circuitsPath)) {
|
||||
fs.mkdirSync(circuitsPath, { recursive: true })
|
||||
fs.mkdirSync(contractsPath, { recursive: true })
|
||||
}
|
||||
for(let asset of assets) {
|
||||
for (let asset of assets) {
|
||||
if (files.includes(asset.name)) {
|
||||
console.log(`Downloading ${asset.name} ...`)
|
||||
await downloadFile({
|
||||
url: asset.browser_download_url,
|
||||
path: path.resolve(__dirname, circuitsPath, asset.name)
|
||||
path: path.resolve(__dirname, circuitsPath, asset.name),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
17
index.html
17
index.html
@ -1,16 +1,17 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Tornado test</title>
|
||||
</head>
|
||||
<body>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Open dev console!<br>
|
||||
Make sure your Metamask is unlocked and connected to Kovan (or other network you've deployed your contract to)<br>
|
||||
Open dev console!<br />
|
||||
Make sure your Metamask is unlocked and connected to Kovan (or other network you've deployed your
|
||||
contract to)<br />
|
||||
<a href="#" onclick="deposit()">Deposit</a>
|
||||
<a href="#" onclick="withdraw()">Withdraw</a>
|
||||
</p>
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -2,7 +2,6 @@ const jsStorage = require('./Storage')
|
||||
const hasherImpl = require('./MiMC')
|
||||
|
||||
class MerkleTree {
|
||||
|
||||
constructor(n_levels, defaultElements, prefix, storage, hasher) {
|
||||
this.prefix = prefix
|
||||
this.storage = storage || new jsStorage()
|
||||
@ -15,9 +14,7 @@ class MerkleTree {
|
||||
this.zero_values.push(current_zero_value)
|
||||
for (let i = 0; i < n_levels; i++) {
|
||||
current_zero_value = this.hasher.hash(i, current_zero_value, current_zero_value)
|
||||
this.zero_values.push(
|
||||
current_zero_value.toString(),
|
||||
)
|
||||
this.zero_values.push(current_zero_value.toString())
|
||||
}
|
||||
if (defaultElements) {
|
||||
let level = 0
|
||||
@ -28,7 +25,7 @@ class MerkleTree {
|
||||
level++
|
||||
let numberOfElementsInLevel = Math.ceil(defaultElements.length / 2)
|
||||
for (level; level <= this.n_levels; level++) {
|
||||
for(let i = 0; i < numberOfElementsInLevel; i++) {
|
||||
for (let i = 0; i < numberOfElementsInLevel; i++) {
|
||||
const leftKey = MerkleTree.index_to_key(prefix, level - 1, 2 * i)
|
||||
const rightKey = MerkleTree.index_to_key(prefix, level - 1, 2 * i + 1)
|
||||
|
||||
@ -93,14 +90,14 @@ class MerkleTree {
|
||||
root,
|
||||
path_elements: traverser.path_elements,
|
||||
path_index: traverser.path_index,
|
||||
element
|
||||
element,
|
||||
}
|
||||
}
|
||||
|
||||
async update(index, element, insert = false) {
|
||||
if (!insert && index >= this.totalElements) {
|
||||
throw Error('Use insert method for new elements.')
|
||||
} else if(insert && index < this.totalElements) {
|
||||
} else if (insert && index < this.totalElements) {
|
||||
throw Error('Use update method for existing elements.')
|
||||
}
|
||||
try {
|
||||
@ -141,13 +138,7 @@ class MerkleTree {
|
||||
this.current_element = this.hasher.hash(level, left, right)
|
||||
}
|
||||
}
|
||||
let traverser = new UpdateTraverser(
|
||||
this.prefix,
|
||||
this.storage,
|
||||
this.hasher,
|
||||
element,
|
||||
this.zero_values
|
||||
)
|
||||
let traverser = new UpdateTraverser(this.prefix, this.storage, this.hasher, element, this.zero_values)
|
||||
|
||||
await this.traverse(index, traverser)
|
||||
traverser.key_values_to_put.push({
|
||||
@ -156,7 +147,7 @@ class MerkleTree {
|
||||
})
|
||||
|
||||
await this.storage.put_batch(traverser.key_values_to_put)
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
@ -182,7 +173,7 @@ class MerkleTree {
|
||||
}
|
||||
|
||||
getIndexByElement(element) {
|
||||
for(let i = this.totalElements - 1; i >= 0; i--) {
|
||||
for (let i = this.totalElements - 1; i >= 0; i--) {
|
||||
const elementFromTree = this.storage.get(MerkleTree.index_to_key(this.prefix, 0, i))
|
||||
if (elementFromTree === element) {
|
||||
return i
|
||||
|
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
class JsStorage {
|
||||
constructor() {
|
||||
this.db = {}
|
||||
@ -30,7 +28,7 @@ class JsStorage {
|
||||
}
|
||||
|
||||
put_batch(key_values) {
|
||||
key_values.forEach(element => {
|
||||
key_values.forEach((element) => {
|
||||
this.db[element.key] = element.value
|
||||
})
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ function send(method, params = []) {
|
||||
jsonrpc: '2.0',
|
||||
id: Date.now(),
|
||||
method,
|
||||
params
|
||||
params,
|
||||
}, (err, res) => {
|
||||
return err ? reject(err) : resolve(res)
|
||||
})
|
||||
@ -48,5 +48,5 @@ module.exports = {
|
||||
minerStop,
|
||||
minerStart,
|
||||
increaseTime,
|
||||
traceTransaction
|
||||
traceTransaction,
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
/* global artifacts */
|
||||
const Migrations = artifacts.require('Migrations')
|
||||
|
||||
module.exports = function(deployer) {
|
||||
if(deployer.network === 'mainnet') {
|
||||
return
|
||||
}
|
||||
deployer.deploy(Migrations)
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/* global artifacts */
|
||||
const Hasher = artifacts.require('Hasher')
|
||||
|
||||
module.exports = async function(deployer) {
|
||||
module.exports = async function (deployer) {
|
||||
await deployer.deploy(Hasher)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* global artifacts */
|
||||
const Verifier = artifacts.require('Verifier')
|
||||
|
||||
module.exports = function(deployer) {
|
||||
module.exports = function (deployer) {
|
||||
deployer.deploy(Verifier)
|
||||
}
|
||||
|
@ -4,14 +4,19 @@ const ETHTornado = artifacts.require('ETHTornado')
|
||||
const Verifier = artifacts.require('Verifier')
|
||||
const hasherContract = artifacts.require('Hasher')
|
||||
|
||||
|
||||
module.exports = function(deployer, network, accounts) {
|
||||
module.exports = function (deployer, network, accounts) {
|
||||
return deployer.then(async () => {
|
||||
const { MERKLE_TREE_HEIGHT, ETH_AMOUNT } = process.env
|
||||
const verifier = await Verifier.deployed()
|
||||
const hasherInstance = await hasherContract.deployed()
|
||||
await ETHTornado.link(hasherContract, hasherInstance.address)
|
||||
const tornado = await deployer.deploy(ETHTornado, verifier.address, ETH_AMOUNT, MERKLE_TREE_HEIGHT, accounts[0])
|
||||
console.log('ETHTornado\'s address ', tornado.address)
|
||||
const tornado = await deployer.deploy(
|
||||
ETHTornado,
|
||||
verifier.address,
|
||||
ETH_AMOUNT,
|
||||
MERKLE_TREE_HEIGHT,
|
||||
accounts[0],
|
||||
)
|
||||
console.log('ETHTornado address ', tornado.address)
|
||||
})
|
||||
}
|
||||
|
@ -5,15 +5,14 @@ const Verifier = artifacts.require('Verifier')
|
||||
const hasherContract = artifacts.require('Hasher')
|
||||
const ERC20Mock = artifacts.require('ERC20Mock')
|
||||
|
||||
|
||||
module.exports = function(deployer, network, accounts) {
|
||||
module.exports = function (deployer, network, accounts) {
|
||||
return deployer.then(async () => {
|
||||
const { MERKLE_TREE_HEIGHT, ERC20_TOKEN, TOKEN_AMOUNT } = process.env
|
||||
const verifier = await Verifier.deployed()
|
||||
const hasherInstance = await hasherContract.deployed()
|
||||
await ERC20Tornado.link(hasherContract, hasherInstance.address)
|
||||
let token = ERC20_TOKEN
|
||||
if(token === '') {
|
||||
if (token === '') {
|
||||
const tokenInstance = await deployer.deploy(ERC20Mock)
|
||||
token = tokenInstance.address
|
||||
}
|
||||
@ -25,6 +24,6 @@ module.exports = function(deployer, network, accounts) {
|
||||
accounts[0],
|
||||
token,
|
||||
)
|
||||
console.log('ERC20Tornado\'s address ', tornado.address)
|
||||
console.log('ERC20Tornado address ', tornado.address)
|
||||
})
|
||||
}
|
||||
|
@ -18,13 +18,15 @@ const AMOUNT = '1'
|
||||
// CURRENCY = 'ETH'
|
||||
|
||||
/** Generate random number of specified byte length */
|
||||
const rbigint = nbytes => bigInt.leBuff2int(crypto.randomBytes(nbytes))
|
||||
const rbigint = (nbytes) => bigInt.leBuff2int(crypto.randomBytes(nbytes))
|
||||
|
||||
/** Compute pedersen hash */
|
||||
const pedersenHash = data => circomlib.babyJub.unpackPoint(circomlib.pedersenHash.hash(data))[0]
|
||||
const pedersenHash = (data) => circomlib.babyJub.unpackPoint(circomlib.pedersenHash.hash(data))[0]
|
||||
|
||||
/** BigNumber to hex string of specified length */
|
||||
const toHex = (number, length = 32) => '0x' + (number instanceof Buffer ? number.toString('hex') : bigInt(number).toString(16)).padStart(length * 2, '0')
|
||||
const toHex = (number, length = 32) =>
|
||||
'0x' +
|
||||
(number instanceof Buffer ? number.toString('hex') : bigInt(number).toString(16)).padStart(length * 2, '0')
|
||||
|
||||
/**
|
||||
* Create deposit object from secret and nullifier
|
||||
@ -43,7 +45,9 @@ function createDeposit(nullifier, secret) {
|
||||
async function deposit() {
|
||||
const deposit = createDeposit(rbigint(31), rbigint(31))
|
||||
console.log('Sending deposit transaction...')
|
||||
const tx = await contract.methods.deposit(toHex(deposit.commitment)).send({ value: toWei(AMOUNT), from: web3.eth.defaultAccount, gas:2e6 })
|
||||
const tx = await contract.methods
|
||||
.deposit(toHex(deposit.commitment))
|
||||
.send({ value: toWei(AMOUNT), from: web3.eth.defaultAccount, gas: 2e6 })
|
||||
console.log(`https://kovan.etherscan.io/tx/${tx.transactionHash}`)
|
||||
return `tornado-eth-${AMOUNT}-${netId}-${toHex(deposit.preimage, 62)}`
|
||||
}
|
||||
@ -87,11 +91,11 @@ async function generateMerkleProof(deposit) {
|
||||
const events = await contract.getPastEvents('Deposit', { fromBlock: 0, toBlock: 'latest' })
|
||||
const leaves = events
|
||||
.sort((a, b) => a.returnValues.leafIndex - b.returnValues.leafIndex) // Sort events in chronological order
|
||||
.map(e => e.returnValues.commitment)
|
||||
.map((e) => e.returnValues.commitment)
|
||||
const tree = new merkleTree(MERKLE_TREE_HEIGHT, leaves)
|
||||
|
||||
// Find current commitment in the tree
|
||||
let depositEvent = events.find(e => e.returnValues.commitment === toHex(deposit.commitment))
|
||||
let depositEvent = events.find((e) => e.returnValues.commitment === toHex(deposit.commitment))
|
||||
let leafIndex = depositEvent ? depositEvent.returnValues.leafIndex : -1
|
||||
|
||||
// Validate that our data is correct (optional)
|
||||
@ -141,14 +145,16 @@ async function generateSnarkProof(deposit, recipient) {
|
||||
toHex(input.recipient, 20),
|
||||
toHex(input.relayer, 20),
|
||||
toHex(input.fee),
|
||||
toHex(input.refund)
|
||||
toHex(input.refund),
|
||||
]
|
||||
|
||||
return { proof, args }
|
||||
}
|
||||
|
||||
async function main() {
|
||||
web3 = new Web3(new Web3.providers.HttpProvider(RPC_URL, { timeout: 5 * 60 * 1000 }), null, { transactionConfirmationBlocks: 1 })
|
||||
web3 = new Web3(new Web3.providers.HttpProvider(RPC_URL, { timeout: 5 * 60 * 1000 }), null, {
|
||||
transactionConfirmationBlocks: 1,
|
||||
})
|
||||
circuit = require('./build/circuits/withdraw.json')
|
||||
proving_key = fs.readFileSync('build/circuits/withdraw_proving_key.bin').buffer
|
||||
groth16 = await buildGroth16()
|
||||
|
8408
package-lock.json
generated
8408
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@ -19,7 +19,10 @@
|
||||
"migrate:kovan": "npx truffle migrate --network kovan --reset",
|
||||
"migrate:rinkeby": "npx truffle migrate --network rinkeby --reset",
|
||||
"migrate:mainnet": "npx truffle migrate --network mainnet",
|
||||
"eslint": "npx eslint --ignore-path .gitignore .",
|
||||
"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",
|
||||
"flat": "npx truffle-flattener contracts/ETHTornado.sol > ETHTornado_flat.sol && npx truffle-flattener contracts/ERC20Tornado.sol > ERC20Tornado_flat.sol",
|
||||
"download": "node downloadKeys.js"
|
||||
},
|
||||
@ -31,6 +34,7 @@
|
||||
"@truffle/contract": "^4.0.39",
|
||||
"@truffle/hdwallet-provider": "^1.0.24",
|
||||
"axios": "^0.19.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"bn-chai": "^1.0.1",
|
||||
"browserify": "^16.5.0",
|
||||
"chai": "^4.2.0",
|
||||
@ -39,10 +43,15 @@
|
||||
"circomlib": "git+https://github.com/tornadocash/circomlib.git#c372f14d324d57339c88451834bf2824e73bbdbc",
|
||||
"commander": "^4.1.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"eslint": "^6.6.0",
|
||||
"eslint": "^7.19.0",
|
||||
"eslint-config-prettier": "^7.2.0",
|
||||
"eslint-plugin-prettier": "^3.3.1",
|
||||
"eth-json-rpc-filters": "^4.1.1",
|
||||
"ganache-cli": "^6.7.0",
|
||||
"prettier": "^2.2.1",
|
||||
"prettier-plugin-solidity": "^1.0.0-beta.3",
|
||||
"snarkjs": "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5",
|
||||
"solhint-plugin-prettier": "^0.0.5",
|
||||
"truffle": "^5.0.44",
|
||||
"truffle-flattener": "^1.4.2",
|
||||
"web3": "^1.2.2",
|
||||
|
@ -1,8 +1,5 @@
|
||||
/* global artifacts, web3, contract */
|
||||
require('chai')
|
||||
.use(require('bn-chai')(web3.utils.BN))
|
||||
.use(require('chai-as-promised'))
|
||||
.should()
|
||||
require('chai').use(require('bn-chai')(web3.utils.BN)).use(require('chai-as-promised')).should()
|
||||
const fs = require('fs')
|
||||
|
||||
const { toBN } = require('web3-utils')
|
||||
@ -25,7 +22,11 @@ const MerkleTree = require('../lib/MerkleTree')
|
||||
|
||||
const rbigint = (nbytes) => snarkjs.bigInt.leBuff2int(crypto.randomBytes(nbytes))
|
||||
const pedersenHash = (data) => circomlib.babyJub.unpackPoint(circomlib.pedersenHash.hash(data))[0]
|
||||
const toFixedHex = (number, length = 32) => '0x' + bigInt(number).toString(16).padStart(length * 2, '0')
|
||||
const toFixedHex = (number, length = 32) =>
|
||||
'0x' +
|
||||
bigInt(number)
|
||||
.toString(16)
|
||||
.padStart(length * 2, '0')
|
||||
const getRandomRecipient = () => rbigint(20)
|
||||
|
||||
function generateDeposit() {
|
||||
@ -38,7 +39,7 @@ function generateDeposit() {
|
||||
return deposit
|
||||
}
|
||||
|
||||
contract('ERC20Tornado', accounts => {
|
||||
contract('ERC20Tornado', (accounts) => {
|
||||
let tornado
|
||||
let token
|
||||
let usdtToken
|
||||
@ -59,11 +60,7 @@ contract('ERC20Tornado', accounts => {
|
||||
let proving_key
|
||||
|
||||
before(async () => {
|
||||
tree = new MerkleTree(
|
||||
levels,
|
||||
null,
|
||||
prefix,
|
||||
)
|
||||
tree = new MerkleTree(levels, null, prefix)
|
||||
tornado = await Tornado.deployed()
|
||||
if (ERC20_TOKEN) {
|
||||
token = await Token.at(ERC20_TOKEN)
|
||||
@ -142,7 +139,6 @@ contract('ERC20Tornado', accounts => {
|
||||
pathIndices: path_index,
|
||||
})
|
||||
|
||||
|
||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||
|
||||
@ -164,7 +160,7 @@ contract('ERC20Tornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
const { logs } = await tornado.withdraw(proof, ...args, { value: refund, from: relayer, gasPrice: '0' })
|
||||
|
||||
@ -177,7 +173,9 @@ contract('ERC20Tornado', accounts => {
|
||||
const feeBN = toBN(fee.toString())
|
||||
balanceTornadoAfter.should.be.eq.BN(toBN(balanceTornadoBefore).sub(toBN(tokenDenomination)))
|
||||
balanceRelayerAfter.should.be.eq.BN(toBN(balanceRelayerBefore).add(feeBN))
|
||||
balanceRecieverAfter.should.be.eq.BN(toBN(balanceRecieverBefore).add(toBN(tokenDenomination).sub(feeBN)))
|
||||
balanceRecieverAfter.should.be.eq.BN(
|
||||
toBN(balanceRecieverBefore).add(toBN(tokenDenomination).sub(feeBN)),
|
||||
)
|
||||
|
||||
ethBalanceOperatorAfter.should.be.eq.BN(toBN(ethBalanceOperatorBefore))
|
||||
ethBalanceRecieverAfter.should.be.eq.BN(toBN(ethBalanceRecieverBefore).add(toBN(refund)))
|
||||
@ -223,7 +221,6 @@ contract('ERC20Tornado', accounts => {
|
||||
pathIndices: path_index,
|
||||
})
|
||||
|
||||
|
||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||
|
||||
@ -243,7 +240,7 @@ contract('ERC20Tornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
const { logs } = await tornado.withdraw(proof, ...args, { value: refund, from: relayer, gasPrice: '0' })
|
||||
|
||||
@ -256,7 +253,9 @@ contract('ERC20Tornado', accounts => {
|
||||
const feeBN = toBN(fee.toString())
|
||||
balanceTornadoAfter.should.be.eq.BN(toBN(balanceTornadoBefore).sub(toBN(tokenDenomination)))
|
||||
balanceRelayerAfter.should.be.eq.BN(toBN(balanceRelayerBefore).add(feeBN))
|
||||
balanceRecieverAfter.should.be.eq.BN(toBN(balanceRecieverBefore).add(toBN(tokenDenomination).sub(feeBN)))
|
||||
balanceRecieverAfter.should.be.eq.BN(
|
||||
toBN(balanceRecieverBefore).add(toBN(tokenDenomination).sub(feeBN)),
|
||||
)
|
||||
|
||||
ethBalanceOperatorAfter.should.be.eq.BN(toBN(ethBalanceOperatorBefore))
|
||||
ethBalanceRecieverAfter.should.be.eq.BN(toBN(ethBalanceRecieverBefore))
|
||||
@ -278,7 +277,6 @@ contract('ERC20Tornado', accounts => {
|
||||
await token.approve(tornado.address, tokenDenomination, { from: user })
|
||||
await tornado.deposit(toFixedHex(deposit.commitment), { from: user, gasPrice: '0' })
|
||||
|
||||
|
||||
const { root, path_elements, path_index } = await tree.path(0)
|
||||
// Circuit input
|
||||
const input = stringifyBigInts({
|
||||
@ -297,7 +295,6 @@ contract('ERC20Tornado', accounts => {
|
||||
pathIndices: path_index,
|
||||
})
|
||||
|
||||
|
||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||
|
||||
@ -307,13 +304,16 @@ contract('ERC20Tornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
let { reason } = await tornado.withdraw(proof, ...args, { value: 1, from: relayer, gasPrice: '0' }).should.be.rejected
|
||||
let { reason } = await tornado.withdraw(proof, ...args, { value: 1, from: relayer, gasPrice: '0' })
|
||||
.should.be.rejected
|
||||
reason.should.be.equal('Incorrect refund amount received by the contract')
|
||||
|
||||
|
||||
;({ reason } = await tornado.withdraw(proof, ...args, { value: toBN(refund).mul(toBN(2)), from: relayer, gasPrice: '0' }).should.be.rejected)
|
||||
;({ reason } = await tornado.withdraw(proof, ...args, {
|
||||
value: toBN(refund).mul(toBN(2)),
|
||||
from: relayer,
|
||||
gasPrice: '0',
|
||||
}).should.be.rejected)
|
||||
reason.should.be.equal('Incorrect refund amount received by the contract')
|
||||
})
|
||||
|
||||
@ -364,7 +364,6 @@ contract('ERC20Tornado', accounts => {
|
||||
pathIndices: path_index,
|
||||
})
|
||||
|
||||
|
||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||
|
||||
@ -385,7 +384,7 @@ contract('ERC20Tornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
const { logs } = await tornado.withdraw(proof, ...args, { value: refund, from: relayer, gasPrice: '0' })
|
||||
|
||||
@ -401,7 +400,6 @@ contract('ERC20Tornado', accounts => {
|
||||
balanceRecieverAfter.should.be.eq.BN(toBN(balanceRecieverBefore).add(toBN(tokenDenomination)))
|
||||
ethBalanceRecieverAfter.should.be.eq.BN(toBN(ethBalanceRecieverBefore).add(toBN(refund)).sub(feeBN))
|
||||
|
||||
|
||||
logs[0].event.should.be.equal('Withdrawal')
|
||||
logs[0].args.nullifierHash.should.be.eq.BN(toBN(input.nullifierHash.toString()))
|
||||
logs[0].args.relayer.should.be.eq.BN(operator)
|
||||
@ -453,7 +451,6 @@ contract('ERC20Tornado', accounts => {
|
||||
pathIndices: path_index,
|
||||
})
|
||||
|
||||
|
||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||
|
||||
@ -474,7 +471,7 @@ contract('ERC20Tornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
const { logs } = await tornado.withdraw(proof, ...args, { value: refund, from: relayer, gasPrice: '0' })
|
||||
console.log('withdraw done')
|
||||
@ -491,7 +488,6 @@ contract('ERC20Tornado', accounts => {
|
||||
balanceRecieverAfter.should.be.eq.BN(toBN(balanceRecieverBefore).add(toBN(tokenDenomination)))
|
||||
ethBalanceRecieverAfter.should.be.eq.BN(toBN(ethBalanceRecieverBefore).add(toBN(refund)).sub(feeBN))
|
||||
|
||||
|
||||
logs[0].event.should.be.equal('Withdrawal')
|
||||
logs[0].args.nullifierHash.should.be.eq.BN(toBN(input.nullifierHash.toString()))
|
||||
logs[0].args.relayer.should.be.eq.BN(operator)
|
||||
@ -505,10 +501,6 @@ contract('ERC20Tornado', accounts => {
|
||||
await revertSnapshot(snapshotId.result)
|
||||
// eslint-disable-next-line require-atomic-updates
|
||||
snapshotId = await takeSnapshot()
|
||||
tree = new MerkleTree(
|
||||
levels,
|
||||
null,
|
||||
prefix,
|
||||
)
|
||||
tree = new MerkleTree(levels, null, prefix)
|
||||
})
|
||||
})
|
||||
|
@ -1,8 +1,5 @@
|
||||
/* global artifacts, web3, contract */
|
||||
require('chai')
|
||||
.use(require('bn-chai')(web3.utils.BN))
|
||||
.use(require('chai-as-promised'))
|
||||
.should()
|
||||
require('chai').use(require('bn-chai')(web3.utils.BN)).use(require('chai-as-promised')).should()
|
||||
const fs = require('fs')
|
||||
|
||||
const { toBN, randomHex } = require('web3-utils')
|
||||
@ -23,7 +20,11 @@ const MerkleTree = require('../lib/MerkleTree')
|
||||
|
||||
const rbigint = (nbytes) => snarkjs.bigInt.leBuff2int(crypto.randomBytes(nbytes))
|
||||
const pedersenHash = (data) => circomlib.babyJub.unpackPoint(circomlib.pedersenHash.hash(data))[0]
|
||||
const toFixedHex = (number, length = 32) => '0x' + bigInt(number).toString(16).padStart(length * 2, '0')
|
||||
const toFixedHex = (number, length = 32) =>
|
||||
'0x' +
|
||||
bigInt(number)
|
||||
.toString(16)
|
||||
.padStart(length * 2, '0')
|
||||
const getRandomRecipient = () => rbigint(20)
|
||||
|
||||
function generateDeposit() {
|
||||
@ -39,7 +40,7 @@ function generateDeposit() {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function BNArrayToStringArray(array) {
|
||||
const arrayToPrint = []
|
||||
array.forEach(item => {
|
||||
array.forEach((item) => {
|
||||
arrayToPrint.push(item.toString())
|
||||
})
|
||||
return arrayToPrint
|
||||
@ -51,7 +52,7 @@ function snarkVerify(proof) {
|
||||
return snarkjs['groth'].isValid(verification_key, proof, proof.publicSignals)
|
||||
}
|
||||
|
||||
contract('ETHTornado', accounts => {
|
||||
contract('ETHTornado', (accounts) => {
|
||||
let tornado
|
||||
const sender = accounts[0]
|
||||
const operator = accounts[0]
|
||||
@ -69,11 +70,7 @@ contract('ETHTornado', accounts => {
|
||||
let proving_key
|
||||
|
||||
before(async () => {
|
||||
tree = new MerkleTree(
|
||||
levels,
|
||||
null,
|
||||
prefix,
|
||||
)
|
||||
tree = new MerkleTree(levels, null, prefix)
|
||||
tornado = await Tornado.deployed()
|
||||
snapshotId = await takeSnapshot()
|
||||
groth16 = await buildGroth16()
|
||||
@ -97,8 +94,8 @@ contract('ETHTornado', accounts => {
|
||||
logs[0].args.commitment.should.be.equal(commitment)
|
||||
logs[0].args.leafIndex.should.be.eq.BN(0)
|
||||
|
||||
commitment = toFixedHex(12);
|
||||
({ logs } = await tornado.deposit(commitment, { value, from: accounts[2] }))
|
||||
commitment = toFixedHex(12)
|
||||
;({ logs } = await tornado.deposit(commitment, { value, from: accounts[2] }))
|
||||
|
||||
logs[0].event.should.be.equal('Deposit')
|
||||
logs[0].args.commitment.should.be.equal(commitment)
|
||||
@ -138,7 +135,8 @@ contract('ETHTornado', accounts => {
|
||||
result.should.be.equal(true)
|
||||
|
||||
// nullifier
|
||||
proofData.publicSignals[1] = '133792158246920651341275668520530514036799294649489851421007411546007850802'
|
||||
proofData.publicSignals[1] =
|
||||
'133792158246920651341275668520530514036799294649489851421007411546007850802'
|
||||
result = snarkVerify(proofData)
|
||||
result.should.be.equal(false)
|
||||
proofData = originalProof
|
||||
@ -192,7 +190,6 @@ contract('ETHTornado', accounts => {
|
||||
pathIndices: path_index,
|
||||
})
|
||||
|
||||
|
||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||
|
||||
@ -212,7 +209,7 @@ contract('ETHTornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
const { logs } = await tornado.withdraw(proof, ...args, { from: relayer, gasPrice: '0' })
|
||||
|
||||
@ -226,7 +223,6 @@ contract('ETHTornado', accounts => {
|
||||
balanceOperatorAfter.should.be.eq.BN(toBN(balanceOperatorBefore).add(feeBN))
|
||||
balanceRecieverAfter.should.be.eq.BN(toBN(balanceRecieverBefore).add(toBN(value)).sub(feeBN))
|
||||
|
||||
|
||||
logs[0].event.should.be.equal('Withdrawal')
|
||||
logs[0].args.nullifierHash.should.be.equal(toFixedHex(input.nullifierHash))
|
||||
logs[0].args.relayer.should.be.eq.BN(operator)
|
||||
@ -262,7 +258,7 @@ contract('ETHTornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
await tornado.withdraw(proof, ...args, { from: relayer }).should.be.fulfilled
|
||||
const error = await tornado.withdraw(proof, ...args, { from: relayer }).should.be.rejected
|
||||
@ -292,11 +288,15 @@ contract('ETHTornado', accounts => {
|
||||
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||
const args = [
|
||||
toFixedHex(input.root),
|
||||
toFixedHex(toBN(input.nullifierHash).add(toBN('21888242871839275222246405745257275088548364400416034343698204186575808495617'))),
|
||||
toFixedHex(
|
||||
toBN(input.nullifierHash).add(
|
||||
toBN('21888242871839275222246405745257275088548364400416034343698204186575808495617'),
|
||||
),
|
||||
),
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
const error = await tornado.withdraw(proof, ...args, { from: relayer }).should.be.rejected
|
||||
error.reason.should.be.equal('verifier-gte-snark-scalar-field')
|
||||
@ -330,7 +330,7 @@ contract('ETHTornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
const error = await tornado.withdraw(proof, ...args, { from: relayer }).should.be.rejected
|
||||
error.reason.should.be.equal('Fee exceeds transfer value')
|
||||
@ -365,7 +365,7 @@ contract('ETHTornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
const error = await tornado.withdraw(proof, ...args, { from: relayer }).should.be.rejected
|
||||
error.reason.should.be.equal('Cannot find your merkle root')
|
||||
@ -398,7 +398,7 @@ contract('ETHTornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
let incorrectArgs
|
||||
const originalProof = proof.slice()
|
||||
@ -410,7 +410,7 @@ contract('ETHTornado', accounts => {
|
||||
toFixedHex('0x0000000000000000000000007a1f9131357404ef86d7c38dbffed2da70321337', 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
let error = await tornado.withdraw(proof, ...incorrectArgs, { from: relayer }).should.be.rejected
|
||||
error.reason.should.be.equal('Invalid withdraw proof')
|
||||
@ -422,7 +422,7 @@ contract('ETHTornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex('0x000000000000000000000000000000000000000000000000015345785d8a0000'),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
error = await tornado.withdraw(proof, ...incorrectArgs, { from: relayer }).should.be.rejected
|
||||
error.reason.should.be.equal('Invalid withdraw proof')
|
||||
@ -434,7 +434,7 @@ contract('ETHTornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
error = await tornado.withdraw(proof, ...incorrectArgs, { from: relayer }).should.be.rejected
|
||||
error.reason.should.be.equal('Invalid withdraw proof')
|
||||
@ -476,7 +476,7 @@ contract('ETHTornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
const error = await tornado.withdraw(proof, ...args, { from: relayer }).should.be.rejected
|
||||
error.reason.should.be.equal('Refund value is supposed to be zero for ETH instance')
|
||||
@ -502,7 +502,6 @@ contract('ETHTornado', accounts => {
|
||||
const newOperator = accounts[7]
|
||||
const error = await tornado.changeOperator(newOperator, { from: accounts[7] }).should.be.rejected
|
||||
error.reason.should.be.equal('Only operator can call this function.')
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
@ -525,7 +524,6 @@ contract('ETHTornado', accounts => {
|
||||
const newVerifier = accounts[7]
|
||||
const error = await tornado.updateVerifier(newVerifier, { from: accounts[7] }).should.be.rejected
|
||||
error.reason.should.be.equal('Only operator can call this function.')
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
@ -557,7 +555,6 @@ contract('ETHTornado', accounts => {
|
||||
pathIndices: path_index,
|
||||
})
|
||||
|
||||
|
||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||
|
||||
@ -567,7 +564,7 @@ contract('ETHTornado', accounts => {
|
||||
toFixedHex(input.recipient, 20),
|
||||
toFixedHex(input.relayer, 20),
|
||||
toFixedHex(input.fee),
|
||||
toFixedHex(input.refund)
|
||||
toFixedHex(input.refund),
|
||||
]
|
||||
|
||||
await tornado.withdraw(proof, ...args, { from: relayer, gasPrice: '0' })
|
||||
@ -583,10 +580,6 @@ contract('ETHTornado', accounts => {
|
||||
await revertSnapshot(snapshotId.result)
|
||||
// eslint-disable-next-line require-atomic-updates
|
||||
snapshotId = await takeSnapshot()
|
||||
tree = new MerkleTree(
|
||||
levels,
|
||||
null,
|
||||
prefix,
|
||||
)
|
||||
tree = new MerkleTree(levels, null, prefix)
|
||||
})
|
||||
})
|
||||
|
@ -1,8 +1,5 @@
|
||||
/* global artifacts, web3, contract, assert */
|
||||
require('chai')
|
||||
.use(require('bn-chai')(web3.utils.BN))
|
||||
.use(require('chai-as-promised'))
|
||||
.should()
|
||||
require('chai').use(require('bn-chai')(web3.utils.BN)).use(require('chai-as-promised')).should()
|
||||
|
||||
const { takeSnapshot, revertSnapshot } = require('../lib/ganacheHelper')
|
||||
|
||||
@ -20,7 +17,7 @@ const { ETH_AMOUNT, MERKLE_TREE_HEIGHT } = process.env
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function BNArrayToStringArray(array) {
|
||||
const arrayToPrint = []
|
||||
array.forEach(item => {
|
||||
array.forEach((item) => {
|
||||
arrayToPrint.push(item.toString())
|
||||
})
|
||||
return arrayToPrint
|
||||
@ -33,7 +30,7 @@ function toFixedHex(number, length = 32) {
|
||||
return str
|
||||
}
|
||||
|
||||
contract('MerkleTreeWithHistory', accounts => {
|
||||
contract('MerkleTreeWithHistory', (accounts) => {
|
||||
let merkleTreeWithHistory
|
||||
let hasherInstance
|
||||
let levels = MERKLE_TREE_HEIGHT || 16
|
||||
@ -46,11 +43,7 @@ contract('MerkleTreeWithHistory', accounts => {
|
||||
let hasher
|
||||
|
||||
before(async () => {
|
||||
tree = new MerkleTree(
|
||||
levels,
|
||||
null,
|
||||
prefix,
|
||||
)
|
||||
tree = new MerkleTree(levels, null, prefix)
|
||||
hasherInstance = await hasherContract.deployed()
|
||||
await MerkleTreeWithHistory.link(hasherContract, hasherInstance.address)
|
||||
merkleTreeWithHistory = await MerkleTreeWithHistory.new(levels)
|
||||
@ -69,40 +62,26 @@ contract('MerkleTreeWithHistory', accounts => {
|
||||
|
||||
describe('merkleTreeLib', () => {
|
||||
it('index_to_key', () => {
|
||||
assert.equal(
|
||||
MerkleTree.index_to_key('test', 5, 20),
|
||||
'test_tree_5_20',
|
||||
)
|
||||
assert.equal(MerkleTree.index_to_key('test', 5, 20), 'test_tree_5_20')
|
||||
})
|
||||
|
||||
it('tests insert', async () => {
|
||||
hasher = new hasherImpl()
|
||||
tree = new MerkleTree(
|
||||
2,
|
||||
null,
|
||||
prefix,
|
||||
)
|
||||
tree = new MerkleTree(2, null, prefix)
|
||||
await tree.insert(toFixedHex('5'))
|
||||
let { root, path_elements } = await tree.path(0)
|
||||
const calculated_root = hasher.hash(null,
|
||||
hasher.hash(null, '5', path_elements[0]),
|
||||
path_elements[1]
|
||||
)
|
||||
const calculated_root = hasher.hash(null, hasher.hash(null, '5', path_elements[0]), path_elements[1])
|
||||
// console.log(root)
|
||||
assert.equal(root, calculated_root)
|
||||
})
|
||||
it('creation odd elements count', async () => {
|
||||
const elements = [12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||
for(const [, el] of Object.entries(elements)) {
|
||||
for (const [, el] of Object.entries(elements)) {
|
||||
await tree.insert(el)
|
||||
}
|
||||
|
||||
const batchTree = new MerkleTree(
|
||||
levels,
|
||||
elements,
|
||||
prefix,
|
||||
)
|
||||
for(const [i] of Object.entries(elements)) {
|
||||
const batchTree = new MerkleTree(levels, elements, prefix)
|
||||
for (const [i] of Object.entries(elements)) {
|
||||
const pathViaConstructor = await batchTree.path(i)
|
||||
const pathViaUpdate = await tree.path(i)
|
||||
pathViaConstructor.should.be.deep.equal(pathViaUpdate)
|
||||
@ -111,7 +90,7 @@ contract('MerkleTreeWithHistory', accounts => {
|
||||
|
||||
it('should find an element', async () => {
|
||||
const elements = [12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||
for(const [, el] of Object.entries(elements)) {
|
||||
for (const [, el] of Object.entries(elements)) {
|
||||
await tree.insert(el)
|
||||
}
|
||||
let index = tree.getIndexByElement(13)
|
||||
@ -132,16 +111,12 @@ contract('MerkleTreeWithHistory', accounts => {
|
||||
|
||||
it('creation even elements count', async () => {
|
||||
const elements = [12, 13, 14, 15, 16, 17]
|
||||
for(const [, el] of Object.entries(elements)) {
|
||||
for (const [, el] of Object.entries(elements)) {
|
||||
await tree.insert(el)
|
||||
}
|
||||
|
||||
const batchTree = new MerkleTree(
|
||||
levels,
|
||||
elements,
|
||||
prefix,
|
||||
)
|
||||
for(const [i] of Object.entries(elements)) {
|
||||
const batchTree = new MerkleTree(levels, elements, prefix)
|
||||
for (const [i] of Object.entries(elements)) {
|
||||
const pathViaConstructor = await batchTree.path(i)
|
||||
const pathViaUpdate = await tree.path(i)
|
||||
pathViaConstructor.should.be.deep.equal(pathViaUpdate)
|
||||
@ -150,15 +125,11 @@ contract('MerkleTreeWithHistory', accounts => {
|
||||
|
||||
it.skip('creation using 30000 elements', () => {
|
||||
const elements = []
|
||||
for(let i = 1000; i < 31001; i++) {
|
||||
for (let i = 1000; i < 31001; i++) {
|
||||
elements.push(i)
|
||||
}
|
||||
console.time('MerkleTree')
|
||||
tree = new MerkleTree(
|
||||
levels,
|
||||
elements,
|
||||
prefix,
|
||||
)
|
||||
tree = new MerkleTree(levels, elements, prefix)
|
||||
console.timeEnd('MerkleTree')
|
||||
// 2,7 GHz Intel Core i7
|
||||
// 1000 : 1949.084ms
|
||||
@ -184,8 +155,8 @@ contract('MerkleTreeWithHistory', accounts => {
|
||||
const levels = 6
|
||||
const merkleTreeWithHistory = await MerkleTreeWithHistory.new(levels)
|
||||
|
||||
for (let i = 0; i < 2**levels; i++) {
|
||||
await merkleTreeWithHistory.insert(toFixedHex(i+42)).should.be.fulfilled
|
||||
for (let i = 0; i < 2 ** levels; i++) {
|
||||
await merkleTreeWithHistory.insert(toFixedHex(i + 42)).should.be.fulfilled
|
||||
}
|
||||
|
||||
let error = await merkleTreeWithHistory.insert(toFixedHex(1337)).should.be.rejected
|
||||
@ -230,18 +201,11 @@ contract('MerkleTreeWithHistory', accounts => {
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
afterEach(async () => {
|
||||
await revertSnapshot(snapshotId.result)
|
||||
// eslint-disable-next-line require-atomic-updates
|
||||
snapshotId = await takeSnapshot()
|
||||
hasher = new hasherImpl()
|
||||
tree = new MerkleTree(
|
||||
levels,
|
||||
null,
|
||||
prefix,
|
||||
null,
|
||||
hasher,
|
||||
)
|
||||
tree = new MerkleTree(levels, null, prefix, null, hasher)
|
||||
})
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
require("dotenv").config();
|
||||
const HDWalletProvider = require("@truffle/hdwallet-provider");
|
||||
const utils = require("web3-utils");
|
||||
require('dotenv').config()
|
||||
const HDWalletProvider = require('@truffle/hdwallet-provider')
|
||||
const utils = require('web3-utils')
|
||||
// const infuraKey = "fj4jll3k.....";
|
||||
//
|
||||
// const fs = require('fs');
|
||||
@ -25,9 +25,9 @@ module.exports = {
|
||||
// options below to some value.
|
||||
|
||||
development: {
|
||||
host: "127.0.0.1", // Localhost (default: none)
|
||||
host: '127.0.0.1', // Localhost (default: none)
|
||||
port: 8545, // Standard Ethereum port (default: none)
|
||||
network_id: "*", // Any network (default: none)
|
||||
network_id: '*', // Any network (default: none)
|
||||
},
|
||||
|
||||
// Another network with more advanced options...
|
||||
@ -46,11 +46,11 @@ module.exports = {
|
||||
provider: () =>
|
||||
new HDWalletProvider(
|
||||
process.env.PRIVATE_KEY,
|
||||
"https://kovan.infura.io/v3/97c8bf358b9942a9853fab1ba93dc5b3"
|
||||
'https://kovan.infura.io/v3/97c8bf358b9942a9853fab1ba93dc5b3',
|
||||
),
|
||||
network_id: 42,
|
||||
gas: 6000000,
|
||||
gasPrice: utils.toWei("1", "gwei"),
|
||||
gasPrice: utils.toWei('1', 'gwei'),
|
||||
// confirmations: 0,
|
||||
// timeoutBlocks: 200,
|
||||
skipDryRun: true,
|
||||
@ -59,11 +59,11 @@ module.exports = {
|
||||
provider: () =>
|
||||
new HDWalletProvider(
|
||||
process.env.PRIVATE_KEY,
|
||||
"https://goerli.infura.io/v3/d34c08f2cb7c4111b645d06ac7e35ba8"
|
||||
'https://goerli.infura.io/v3/d34c08f2cb7c4111b645d06ac7e35ba8',
|
||||
),
|
||||
network_id: 5,
|
||||
gas: 6000000,
|
||||
gasPrice: utils.toWei("1", "gwei"),
|
||||
gasPrice: utils.toWei('1', 'gwei'),
|
||||
// confirmations: 0,
|
||||
// timeoutBlocks: 200,
|
||||
skipDryRun: true,
|
||||
@ -72,24 +72,20 @@ module.exports = {
|
||||
provider: () =>
|
||||
new HDWalletProvider(
|
||||
process.env.PRIVATE_KEY,
|
||||
"https://rinkeby.infura.io/v3/97c8bf358b9942a9853fab1ba93dc5b3"
|
||||
'https://rinkeby.infura.io/v3/97c8bf358b9942a9853fab1ba93dc5b3',
|
||||
),
|
||||
network_id: 4,
|
||||
gas: 6000000,
|
||||
gasPrice: utils.toWei("1", "gwei"),
|
||||
gasPrice: utils.toWei('1', 'gwei'),
|
||||
// confirmations: 0,
|
||||
// timeoutBlocks: 200,
|
||||
skipDryRun: true,
|
||||
},
|
||||
mainnet: {
|
||||
provider: () =>
|
||||
new HDWalletProvider(
|
||||
process.env.PRIVATE_KEY,
|
||||
"http://ethereum-rpc.trustwalletapp.com"
|
||||
),
|
||||
provider: () => new HDWalletProvider(process.env.PRIVATE_KEY, 'http://ethereum-rpc.trustwalletapp.com'),
|
||||
network_id: 1,
|
||||
gas: 6000000,
|
||||
gasPrice: utils.toWei("2", "gwei"),
|
||||
gasPrice: utils.toWei('2', 'gwei'),
|
||||
// confirmations: 0,
|
||||
// timeoutBlocks: 200,
|
||||
skipDryRun: true,
|
||||
@ -111,7 +107,7 @@ module.exports = {
|
||||
// Configure your compilers
|
||||
compilers: {
|
||||
solc: {
|
||||
version: "0.6.12", // Fetch exact version from solc-bin (default: truffle's version)
|
||||
version: '0.6.12', // Fetch exact version from solc-bin (default: truffle's version)
|
||||
// docker: true, // Use "0.5.1" you've installed locally with docker (default: false)
|
||||
settings: {
|
||||
// See the solidity docs for advice about optimization and evmVersion
|
||||
@ -123,12 +119,12 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
external: {
|
||||
command: "node ./compileHasher.js",
|
||||
command: 'node ./compileHasher.js',
|
||||
targets: [
|
||||
{
|
||||
path: "./build/Hasher.json",
|
||||
path: './build/Hasher.json',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user