Merge pull request #18 from peppersec/audit-2

Code style fixes for audit (batch 2)
This commit is contained in:
Roman Semenov 2019-11-06 01:09:46 +03:00 committed by GitHub
commit fce4b1854c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 130 additions and 182 deletions

View File

@ -2,7 +2,6 @@ MERKLE_TREE_HEIGHT=16
# in wei
ETH_AMOUNT=100000000000000000
TOKEN_AMOUNT=100000000000000000
EMPTY_ELEMENT=1
PRIVATE_KEY=
ERC20_TOKEN=

8
cli.js
View File

@ -13,7 +13,7 @@ const buildGroth16 = require('websnark/src/groth16')
const websnarkUtils = require('websnark/src/utils')
let web3, mixer, erc20mixer, circuit, proving_key, groth16, erc20
let MERKLE_TREE_HEIGHT, ETH_AMOUNT, EMPTY_ELEMENT, ERC20_TOKEN
let MERKLE_TREE_HEIGHT, ETH_AMOUNT, ERC20_TOKEN
const inBrowser = (typeof window !== 'undefined')
/** Generate random number of specified byte length */
@ -83,7 +83,7 @@ async function withdrawErc20(note, receiver, relayer) {
}
return e.returnValues.commitment
})
const tree = new merkleTree(MERKLE_TREE_HEIGHT, EMPTY_ELEMENT, leaves)
const tree = new merkleTree(MERKLE_TREE_HEIGHT, leaves)
const validRoot = await erc20mixer.methods.isKnownRoot(await tree.root()).call()
const nullifierHash = pedersenHash(deposit.nullifier.leInt2Buff(31))
const nullifierHashToCheck = nullifierHash.toString(16).padStart('66', '0x000000')
@ -152,7 +152,7 @@ async function withdraw(note, receiver) {
const leaves = events
.sort((a, b) => a.returnValues.leafIndex.sub(b.returnValues.leafIndex)) // Sort events in chronological order
.map(e => e.returnValues.commitment)
const tree = new merkleTree(MERKLE_TREE_HEIGHT, EMPTY_ELEMENT, leaves)
const tree = new merkleTree(MERKLE_TREE_HEIGHT, leaves)
// Find current commitment in the tree
let depositEvent = events.find(e => e.returnValues.commitment.eq(paddedCommitment))
@ -210,7 +210,6 @@ async function init() {
proving_key = await (await fetch('build/circuits/withdraw_proving_key.bin')).arrayBuffer()
MERKLE_TREE_HEIGHT = 16
ETH_AMOUNT = 1e18
EMPTY_ELEMENT = 1
} else {
// Initialize from local node
web3 = new Web3('http://localhost:8545', null, { transactionConfirmationBlocks: 1 })
@ -220,7 +219,6 @@ async function init() {
require('dotenv').config()
MERKLE_TREE_HEIGHT = process.env.MERKLE_TREE_HEIGHT
ETH_AMOUNT = process.env.ETH_AMOUNT
EMPTY_ELEMENT = process.env.EMPTY_ELEMENT
ERC20_TOKEN = process.env.ERC20_TOKEN
erc20ContractJson = require('./build/contracts/ERC20Mock.json')
erc20mixerJson = require('./build/contracts/ERC20Mixer.json')

View File

@ -20,68 +20,49 @@ contract ERC20Mixer is Mixer {
IVerifier _verifier,
uint256 _denomination,
uint8 _merkleTreeHeight,
uint256 _emptyElement,
address _operator,
address _token
) Mixer(_verifier, _denomination, _merkleTreeHeight, _emptyElement, _operator) public {
) Mixer(_verifier, _denomination, _merkleTreeHeight, _operator) public {
token = _token;
}
function _processDeposit() internal {
require(msg.value == 0, "ETH value is supposed to be 0 for ETH mixer");
safeErc20TransferFrom(msg.sender, address(this), denomination);
_safeErc20TransferFrom(msg.sender, address(this), denomination);
}
function _processWithdraw(address payable _receiver, address payable _relayer, uint256 _fee, uint256 _refund) internal {
require(msg.value == _refund, "Incorrect refund amount received by the contract");
safeErc20Transfer(_receiver, denomination - _fee);
_safeErc20Transfer(_receiver, denomination - _fee);
if (_fee > 0) {
safeErc20Transfer(_relayer, _fee);
_safeErc20Transfer(_relayer, _fee);
}
if (_refund > 0) {
_receiver.transfer(_refund);
}
}
function safeErc20TransferFrom(address from, address to, uint256 amount) internal {
bool success;
bytes memory data;
bytes4 transferFromSelector = 0x23b872dd;
(success, data) = token.call(
abi.encodeWithSelector(
transferFromSelector,
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 let's make sure that is `true` according to standard
// if contract returns some data lets make sure that is `true` according to standard
if (data.length > 0) {
assembly {
success := mload(add(data, 0x20))
}
require(data.length == 32, "data length should be either 0 or 32 bytes");
success = abi.decode(data, (bool));
require(success, "not enough allowed tokens");
}
}
function safeErc20Transfer(address to, uint256 amount) internal {
bool success;
bytes memory data;
bytes4 transferSelector = 0xa9059cbb;
(success, data) = token.call(
abi.encodeWithSelector(
transferSelector,
to, amount
)
);
function _safeErc20Transfer(address _to, uint256 _amount) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb /* transfer */, _to, _amount));
require(success, "not enough tokens");
// if contract returns some data let's make sure that is `true` according to standard
// if contract returns some data lets make sure that is `true` according to standard
if (data.length > 0) {
assembly {
success := mload(add(data, 0x20))
}
require(data.length == 32, "data length should be either 0 or 32 bytes");
success = abi.decode(data, (bool));
require(success, "not enough tokens");
}
}

View File

@ -18,9 +18,12 @@ contract ETHMixer is Mixer {
IVerifier _verifier,
uint256 _denomination,
uint8 _merkleTreeHeight,
uint256 _emptyElement,
address _operator
) Mixer(_verifier, _denomination, _merkleTreeHeight, _emptyElement, _operator) public {
) Mixer(_verifier, _denomination, _merkleTreeHeight, _operator) public {
}
function _processDeposit() internal {
require(msg.value == denomination, "Please send `mixDenomination` ETH along with transaction");
}
function _processWithdraw(address payable _receiver, address payable _relayer, uint256 _fee, uint256 _refund) internal {
@ -33,8 +36,4 @@ contract ETHMixer is Mixer {
_relayer.transfer(_fee);
}
}
function _processDeposit() internal {
require(msg.value == denomination, "Please send `mixDenomination` ETH along with transaction");
}
}

View File

@ -16,122 +16,108 @@ library Hasher {
}
contract MerkleTreeWithHistory {
uint256 public constant FIELD_SIZE = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
uint256 public constant ZERO_VALUE = 5702960885942360421128284892092891246826997279710054143430547229469817701242; // = MiMC("tornado")
uint256 public levels;
uint256 constant FIELD_SIZE = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
uint256 constant ROOT_HISTORY_SIZE = 100;
uint256[ROOT_HISTORY_SIZE] public _roots;
uint256 public current_root_index = 0;
// the following variables are made public for easier testing and debugging and
// are not supposed to be accessed in regular code
uint256 public constant ROOT_HISTORY_SIZE = 100;
uint256[ROOT_HISTORY_SIZE] public roots;
uint256 public currentRootIndex = 0;
uint32 public nextIndex = 0;
uint256[] public filledSubtrees;
uint256[] public zeros;
uint256[] private _filled_subtrees;
uint256[] private _zeros;
constructor(uint256 _treeLevels) public {
require(_treeLevels > 0, "_treeLevels should be greater than zero");
levels = _treeLevels;
uint32 public next_index = 0;
constructor(uint256 tree_levels, uint256 zero_value) public {
require(tree_levels > 0, "tree_levels should be greater than zero");
levels = tree_levels;
uint256 current_zero = zero_value;
_zeros.push(zero_value);
_filled_subtrees.push(current_zero);
uint256 currentZero = ZERO_VALUE;
zeros.push(currentZero);
filledSubtrees.push(currentZero);
for (uint8 i = 1; i < levels; i++) {
current_zero = hashLeftRight(current_zero, current_zero);
_zeros.push(current_zero);
_filled_subtrees.push(current_zero);
currentZero = hashLeftRight(currentZero, currentZero);
zeros.push(currentZero);
filledSubtrees.push(currentZero);
}
_roots[0] = hashLeftRight(current_zero, current_zero);
roots[0] = hashLeftRight(currentZero, currentZero);
}
function hashLeftRight(uint256 left, uint256 right) public pure returns (uint256 hash) {
uint256 R = left; // left is already checked to be less than field_size by snark verifier
/**
@dev Hash 2 tree leaves, returns MiMC(_left, _right)
*/
function hashLeftRight(uint256 _left, uint256 _right) public pure returns (uint256) {
require(_left < FIELD_SIZE, "_left should be inside the field");
require(_right < FIELD_SIZE, "_right should be inside the field");
uint256 R = _left;
uint256 C = 0;
(R, C) = Hasher.MiMCSponge(R, C, 0);
R = addmod(R, right, FIELD_SIZE);
R = addmod(R, _right, FIELD_SIZE);
(R, C) = Hasher.MiMCSponge(R, C, 0);
return R;
}
function _insert(uint256 leaf) internal returns(uint256 index) {
uint32 current_index = next_index;
require(current_index != 2**levels, "Merkle tree is full. No more leafs can be added");
next_index += 1;
uint256 current_level_hash = leaf;
function _insert(uint256 _leaf) internal returns(uint256 index) {
uint32 currentIndex = nextIndex;
require(currentIndex != 2**levels, "Merkle tree is full. No more leafs can be added");
nextIndex += 1;
uint256 currentLevelHash = _leaf;
uint256 left;
uint256 right;
for (uint256 i = 0; i < levels; i++) {
if (current_index % 2 == 0) {
left = current_level_hash;
right = _zeros[i];
if (currentIndex % 2 == 0) {
left = currentLevelHash;
right = zeros[i];
_filled_subtrees[i] = current_level_hash;
filledSubtrees[i] = currentLevelHash;
} else {
left = _filled_subtrees[i];
right = current_level_hash;
left = filledSubtrees[i];
right = currentLevelHash;
}
current_level_hash = hashLeftRight(left, right);
currentLevelHash = hashLeftRight(left, right);
current_index /= 2;
currentIndex /= 2;
}
current_root_index = (current_root_index + 1) % ROOT_HISTORY_SIZE;
_roots[current_root_index] = current_level_hash;
return next_index - 1;
currentRootIndex = (currentRootIndex + 1) % ROOT_HISTORY_SIZE;
roots[currentRootIndex] = currentLevelHash;
return nextIndex - 1;
}
function isKnownRoot(uint256 root) public view returns(bool) {
if (root == 0) {
/**
@dev Whether the root is present in the root history
*/
function isKnownRoot(uint256 _root) public view returns(bool) {
if (_root == 0) {
return false;
}
// search most recent first
uint256 i;
for(i = current_root_index; i < 2**256 - 1; i--) {
if (root == _roots[i]) {
for(i = currentRootIndex; i < 2**256 - 1; i--) {
if (_root == roots[i]) {
return true;
}
}
// process the rest of roots
for(i = ROOT_HISTORY_SIZE - 1; i > current_root_index; i--) {
if (root == _roots[i]) {
for(i = ROOT_HISTORY_SIZE - 1; i > currentRootIndex; i--) {
if (_root == roots[i]) {
return true;
}
}
return false;
// or we can do that in other way
// uint256 i = _current_root;
// do {
// if (root == _roots[i]) {
// return true;
// }
// if (i == 0) {
// i = ROOT_HISTORY_SIZE;
// }
// i--;
// } while (i != _current_root);
}
/**
@dev Returns the last root
*/
function getLastRoot() public view returns(uint256) {
return _roots[current_root_index];
}
function roots() public view returns(uint256[ROOT_HISTORY_SIZE] memory) {
return _roots;
}
function filled_subtrees() public view returns(uint256[] memory) {
return _filled_subtrees;
}
function zeros() public view returns(uint256[] memory) {
return _zeros;
return roots[currentRootIndex];
}
}

View File

@ -14,7 +14,7 @@ pragma solidity ^0.5.8;
import "./MerkleTreeWithHistory.sol";
contract IVerifier {
function verifyProof(uint256[8] memory proof, uint256[6] memory input) public returns(bool);
function verifyProof(uint256[8] memory _proof, uint256[6] memory _input) public returns(bool);
}
contract Mixer is MerkleTreeWithHistory {
@ -25,7 +25,6 @@ contract Mixer is MerkleTreeWithHistory {
IVerifier public verifier;
// operator can
// - receive a relayer fee
// - disable new deposits in case of emergency
// - update snark verification key until this ability is permanently disabled
address public operator;
@ -37,22 +36,21 @@ contract Mixer is MerkleTreeWithHistory {
}
event Deposit(uint256 indexed commitment, uint256 leafIndex, uint256 timestamp);
event Withdraw(address to, uint256 nullifierHash, address indexed relayer, uint256 fee);
event Withdrawal(address to, uint256 nullifierHash, address indexed relayer, uint256 fee);
/**
@dev The constructor
@param _verifier the address of SNARK verifier for this contract
@param _denomination transfer amount for each deposit
@param _merkleTreeHeight the height of deposits' Merkle Tree
@param _emptyElement default element of the deposits' Merkle Tree
@param _operator operator address (see operator above)
@param _operator operator address (see operator comment above)
*/
constructor(
IVerifier _verifier,
uint256 _denomination,
uint8 _merkleTreeHeight,
uint256 _emptyElement,
address _operator
) MerkleTreeWithHistory(_merkleTreeHeight, _emptyElement) public {
) MerkleTreeWithHistory(_merkleTreeHeight) public {
require(_denomination > 0, "denomination should be greater than 0");
verifier = _verifier;
operator = _operator;
@ -61,52 +59,52 @@ contract Mixer is MerkleTreeWithHistory {
/**
@dev Deposit funds into mixer. The caller must send (for ETH) or approve (for ERC20) value equal to or `denomination` of this mixer.
@param commitment the note commitment, which is PedersenHash(nullifier + secret)
@param _commitment the note commitment, which is PedersenHash(nullifier + secret)
*/
function deposit(uint256 commitment) public payable {
function deposit(uint256 _commitment) public payable {
require(!isDepositsDisabled, "deposits are disabled");
require(!commitments[commitment], "The commitment has been submitted");
uint256 insertedIndex = _insert(commitment);
commitments[commitment] = true;
require(!commitments[_commitment], "The commitment has been submitted");
uint256 insertedIndex = _insert(_commitment);
commitments[_commitment] = true;
_processDeposit();
emit Deposit(commitment, insertedIndex, block.timestamp);
emit Deposit(_commitment, insertedIndex, block.timestamp);
}
/** @dev this function is defined in a child contract */
function _processDeposit() internal;
/**
@dev Withdraw deposit from the mixer. `proof` is a zkSNARK proof data, and input is an array of circuit public inputs
@dev Withdraw a deposit from the mixer. `proof` is a zkSNARK proof data, and input is an array of circuit public inputs
`input` array consists of:
- merkle root of all deposits in the mixer
- hash of unique deposit nullifier to prevent double spends
- the receiver of funds
- optional fee that goes to the transaction sender (usually a relay)
*/
function withdraw(uint256[8] memory proof, uint256[6] memory input) public payable {
uint256 root = input[0];
uint256 nullifierHash = input[1];
address payable receiver = address(input[2]);
address payable relayer = address(input[3]);
uint256 fee = input[4];
uint256 refund = input[5];
function withdraw(uint256[8] memory _proof, uint256[6] memory _input) public payable {
uint256 root = _input[0];
uint256 nullifierHash = _input[1];
address payable receiver = address(_input[2]);
address payable relayer = address(_input[3]);
uint256 fee = _input[4];
uint256 refund = _input[5];
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, input), "Invalid withdraw proof");
require(verifier.verifyProof(_proof, _input), "Invalid withdraw proof");
nullifierHashes[nullifierHash] = true;
_processWithdraw(receiver, relayer, fee, refund);
emit Withdraw(receiver, nullifierHash, relayer, fee);
emit Withdrawal(receiver, nullifierHash, relayer, fee);
}
/** @dev this function is defined in a child contract */
function _processWithdraw(address payable _receiver, address payable _relayer, uint256 _fee, uint256 _refund) internal;
/** @dev whether a note is already spent */
function isSpent(uint256 nullifierHash) public view returns(bool) {
return nullifierHashes[nullifierHash];
function isSpent(uint256 _nullifierHash) public view returns(bool) {
return nullifierHashes[_nullifierHash];
}
/**
@ -121,9 +119,9 @@ contract Mixer is MerkleTreeWithHistory {
@dev allow operator to update SNARK verification keys. This is needed to update keys after the final trusted setup ceremony is held.
After that operator is supposed to permanently disable this ability.
*/
function updateVerifier(address newVerifier) external onlyOperator {
function updateVerifier(address _newVerifier) external onlyOperator {
require(!isVerifierUpdateDisabled, "Verifier updates have been disabled.");
verifier = IVerifier(newVerifier);
verifier = IVerifier(_newVerifier);
}
/**

View File

@ -4,9 +4,9 @@ import '../MerkleTreeWithHistory.sol';
contract MerkleTreeWithHistoryMock is MerkleTreeWithHistory {
constructor (uint8 tree_levels, uint256 zero_value) MerkleTreeWithHistory(tree_levels, zero_value) public {}
constructor (uint8 _treeLevels) MerkleTreeWithHistory(_treeLevels) public {}
function insert(uint256 leaf) public {
_insert(leaf);
function insert(uint256 _leaf) public {
_insert(_leaf);
}
}

View File

@ -1,9 +1,10 @@
const jsStorage = require('./Storage')
const hasherImpl = require('./MiMC')
const { bigInt } = require('snarkjs')
class MerkleTree {
constructor(n_levels, zero_value, defaultElements, prefix, storage, hasher) {
constructor(n_levels, defaultElements, prefix, storage, hasher) {
this.prefix = prefix
this.storage = storage || new jsStorage()
this.hasher = hasher || new hasherImpl()
@ -11,7 +12,7 @@ class MerkleTree {
this.zero_values = []
this.totalElements = 0
let current_zero_value = zero_value || 0
let current_zero_value = bigInt('5702960885942360421128284892092891246826997279710054143430547229469817701242')
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)

View File

@ -7,11 +7,11 @@ const hasherContract = artifacts.require('Hasher')
module.exports = function(deployer, network, accounts) {
return deployer.then(async () => {
const { MERKLE_TREE_HEIGHT, ETH_AMOUNT, EMPTY_ELEMENT } = process.env
const { MERKLE_TREE_HEIGHT, ETH_AMOUNT } = process.env
const verifier = await Verifier.deployed()
const hasherInstance = await hasherContract.deployed()
await ETHMixer.link(hasherContract, hasherInstance.address)
const mixer = await deployer.deploy(ETHMixer, verifier.address, ETH_AMOUNT, MERKLE_TREE_HEIGHT, EMPTY_ELEMENT, accounts[0])
const mixer = await deployer.deploy(ETHMixer, verifier.address, ETH_AMOUNT, MERKLE_TREE_HEIGHT, accounts[0])
console.log('ETHMixer\'s address ', mixer.address)
})
}

View File

@ -8,7 +8,7 @@ const ERC20Mock = artifacts.require('ERC20Mock')
module.exports = function(deployer, network, accounts) {
return deployer.then(async () => {
const { MERKLE_TREE_HEIGHT, EMPTY_ELEMENT, ERC20_TOKEN, TOKEN_AMOUNT } = process.env
const { MERKLE_TREE_HEIGHT, ERC20_TOKEN, TOKEN_AMOUNT } = process.env
const verifier = await Verifier.deployed()
const hasherInstance = await hasherContract.deployed()
await ERC20Mixer.link(hasherContract, hasherInstance.address)
@ -22,7 +22,6 @@ module.exports = function(deployer, network, accounts) {
verifier.address,
TOKEN_AMOUNT,
MERKLE_TREE_HEIGHT,
EMPTY_ELEMENT,
accounts[0],
token,
)

View File

@ -11,7 +11,7 @@ const { takeSnapshot, revertSnapshot } = require('../lib/ganacheHelper')
const Mixer = artifacts.require('./ERC20Mixer.sol')
const Token = artifacts.require('./ERC20Mock.sol')
const USDTToken = artifacts.require('./IUSDT.sol')
const { ETH_AMOUNT, TOKEN_AMOUNT, MERKLE_TREE_HEIGHT, EMPTY_ELEMENT, ERC20_TOKEN } = process.env
const { ETH_AMOUNT, TOKEN_AMOUNT, MERKLE_TREE_HEIGHT, ERC20_TOKEN } = process.env
const websnarkUtils = require('websnark/src/utils')
const buildGroth16 = require('websnark/src/groth16')
@ -50,7 +50,6 @@ contract('ERC20Mixer', accounts => {
const sender = accounts[0]
const operator = accounts[0]
const levels = MERKLE_TREE_HEIGHT || 16
const zeroValue = EMPTY_ELEMENT || 1337
let tokenDenomination = TOKEN_AMOUNT || '1000000000000000000' // 1 ether
let snapshotId
let prefix = 'test'
@ -66,7 +65,6 @@ contract('ERC20Mixer', accounts => {
before(async () => {
tree = new MerkleTree(
levels,
zeroValue,
null,
prefix,
)
@ -180,7 +178,7 @@ contract('ERC20Mixer', accounts => {
ethBalanceRecieverAfter.should.be.eq.BN(toBN(ethBalanceRecieverBefore).add(toBN(refund)))
ethBalanceRelayerAfter.should.be.eq.BN(toBN(ethBalanceRelayerBefore).sub(toBN(refund)))
logs[0].event.should.be.equal('Withdraw')
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(relayer)
logs[0].args.fee.should.be.eq.BN(feeBN)
@ -304,7 +302,7 @@ contract('ERC20Mixer', accounts => {
ethBalanceRecieverAfter.should.be.eq.BN(toBN(ethBalanceRecieverBefore).add(toBN(refund)).sub(feeBN))
logs[0].event.should.be.equal('Withdraw')
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)
logs[0].args.fee.should.be.eq.BN(feeBN)
@ -386,7 +384,7 @@ contract('ERC20Mixer', accounts => {
ethBalanceRecieverAfter.should.be.eq.BN(toBN(ethBalanceRecieverBefore).add(toBN(refund)).sub(feeBN))
logs[0].event.should.be.equal('Withdraw')
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)
logs[0].args.fee.should.be.eq.BN(feeBN)
@ -401,7 +399,6 @@ contract('ERC20Mixer', accounts => {
snapshotId = await takeSnapshot()
tree = new MerkleTree(
levels,
zeroValue,
null,
prefix,
)

View File

@ -9,7 +9,7 @@ const { toBN, toHex, randomHex } = require('web3-utils')
const { takeSnapshot, revertSnapshot } = require('../lib/ganacheHelper')
const Mixer = artifacts.require('./ETHMixer.sol')
const { ETH_AMOUNT, MERKLE_TREE_HEIGHT, EMPTY_ELEMENT } = process.env
const { ETH_AMOUNT, MERKLE_TREE_HEIGHT } = process.env
const websnarkUtils = require('websnark/src/utils')
const buildGroth16 = require('websnark/src/groth16')
@ -62,7 +62,6 @@ contract('ETHMixer', accounts => {
const sender = accounts[0]
const operator = accounts[0]
const levels = MERKLE_TREE_HEIGHT || 16
const zeroValue = EMPTY_ELEMENT || 1337
const value = ETH_AMOUNT || '1000000000000000000' // 1 ether
let snapshotId
let prefix = 'test'
@ -78,7 +77,6 @@ contract('ETHMixer', accounts => {
before(async () => {
tree = new MerkleTree(
levels,
zeroValue,
null,
prefix,
)
@ -242,7 +240,7 @@ contract('ETHMixer', accounts => {
balanceRecieverAfter.should.be.eq.BN(toBN(balanceRecieverBefore).add(toBN(value)).sub(feeBN))
logs[0].event.should.be.equal('Withdraw')
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)
logs[0].args.fee.should.be.eq.BN(feeBN)
@ -521,7 +519,6 @@ contract('ETHMixer', accounts => {
snapshotId = await takeSnapshot()
tree = new MerkleTree(
levels,
zeroValue,
null,
prefix,
)

View File

@ -12,7 +12,7 @@ const hasherContract = artifacts.require('./Hasher.sol')
const MerkleTree = require('../lib/MerkleTree')
const hasherImpl = require('../lib/MiMC')
const { ETH_AMOUNT, MERKLE_TREE_HEIGHT, EMPTY_ELEMENT } = process.env
const { ETH_AMOUNT, MERKLE_TREE_HEIGHT } = process.env
// eslint-disable-next-line no-unused-vars
function BNArrayToStringArray(array) {
@ -27,7 +27,6 @@ contract('MerkleTreeWithHistory', accounts => {
let merkleTreeWithHistory
let hasherInstance
let levels = MERKLE_TREE_HEIGHT || 16
let zeroValue = EMPTY_ELEMENT || 1337
const sender = accounts[0]
// eslint-disable-next-line no-unused-vars
const value = ETH_AMOUNT || '1000000000000000000'
@ -39,22 +38,22 @@ contract('MerkleTreeWithHistory', accounts => {
before(async () => {
tree = new MerkleTree(
levels,
zeroValue,
null,
prefix,
)
hasherInstance = await hasherContract.deployed()
await MerkleTreeWithHistory.link(hasherContract, hasherInstance.address)
merkleTreeWithHistory = await MerkleTreeWithHistory.new(levels, zeroValue)
merkleTreeWithHistory = await MerkleTreeWithHistory.new(levels)
snapshotId = await takeSnapshot()
})
describe('#constructor', () => {
it('should initialize', async () => {
const filled_subtrees = await merkleTreeWithHistory.filled_subtrees()
filled_subtrees[0].should.be.eq.BN(zeroValue)
const zeros = await merkleTreeWithHistory.zeros()
zeros[0].should.be.eq.BN(zeroValue)
const zeroValue = await merkleTreeWithHistory.ZERO_VALUE()
const firstSubtree = await merkleTreeWithHistory.filledSubtrees(0)
firstSubtree.should.be.eq.BN(zeroValue)
const firstZero = await merkleTreeWithHistory.zeros(0)
firstZero.should.be.eq.BN(zeroValue)
})
})
@ -70,7 +69,6 @@ contract('MerkleTreeWithHistory', accounts => {
hasher = new hasherImpl()
tree = new MerkleTree(
2,
zeroValue,
null,
prefix,
)
@ -91,7 +89,6 @@ contract('MerkleTreeWithHistory', accounts => {
const batchTree = new MerkleTree(
levels,
zeroValue,
elements,
prefix,
)
@ -131,7 +128,6 @@ contract('MerkleTreeWithHistory', accounts => {
const batchTree = new MerkleTree(
levels,
zeroValue,
elements,
prefix,
)
@ -150,7 +146,6 @@ contract('MerkleTreeWithHistory', accounts => {
console.time('MerkleTree')
tree = new MerkleTree(
levels,
zeroValue,
elements,
prefix,
)
@ -177,8 +172,7 @@ contract('MerkleTreeWithHistory', accounts => {
it('should reject if tree is full', async () => {
levels = 6
zeroValue = 1337
merkleTreeWithHistory = await MerkleTreeWithHistory.new(levels, zeroValue)
merkleTreeWithHistory = await MerkleTreeWithHistory.new(levels)
for (let i = 0; i < 2**levels; i++) {
await merkleTreeWithHistory.insert(i+42).should.be.fulfilled
@ -193,8 +187,8 @@ contract('MerkleTreeWithHistory', accounts => {
it.skip('hasher gas', async () => {
levels = 6
zeroValue = 1337
merkleTreeWithHistory = await MerkleTreeWithHistory.new(levels, zeroValue)
merkleTreeWithHistory = await MerkleTreeWithHistory.new(levels)
const zeroValue = await merkleTreeWithHistory.zeroValue()
const gas = await merkleTreeWithHistory.hashLeftRight.estimateGas(zeroValue, zeroValue)
console.log('gas', gas - 21000)
@ -208,7 +202,6 @@ contract('MerkleTreeWithHistory', accounts => {
hasher = new hasherImpl()
tree = new MerkleTree(
levels,
zeroValue,
null,
prefix,
null,