diff --git a/README.md b/README.md index 3b0661c..631f2f7 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ Check config.js for actual values. With `salt` = `0x0000000000000000000000000000000000000000000000000000000047941987` addresses must be: -1. `L1Unwrapper` - `0x095f741D37DfB3C798327377467eD40EE21b3B24` -2. `TornadoPool` - `0x85a3C2E4f0FcD4e881e0a3D1078496660C74bb35` +1. `L1Unwrapper` - `0x3F615bA21Bc6Cc5D4a6D798c5950cc5c42937fbd` +2. `TornadoPool` - `0x0CDD3705aF7979fBe80A64288Ebf8A9Fe1151cE1` Check addresses with current config: diff --git a/config.js b/config.js index 0bd2fcd..669bb3e 100644 --- a/config.js +++ b/config.js @@ -19,7 +19,7 @@ module.exports = { hasher: '0x94c92f096437ab9958fc0a37f09348f30389ae79', gcWeth: '0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1', gcOmniBridge: '0xf6a78083ca3e2a662d6dd1703c939c8ace2e268d', - l1Unwrapper: '0x095f741D37DfB3C798327377467eD40EE21b3B24', + l1Unwrapper: '0x3F615bA21Bc6Cc5D4a6D798c5950cc5c42937fbd', govAddress: '0x5efda50f22d34f262c29268506c5fa42cb56a1ce', l1ChainId: 1, gcMultisig: '0x1f727de610030a88863d7da45bdea4eb84655b52', diff --git a/contracts/TornadoPool.sol b/contracts/TornadoPool.sol index 8ed1de1..8744774 100644 --- a/contracts/TornadoPool.sol +++ b/contracts/TornadoPool.sol @@ -35,7 +35,7 @@ contract TornadoPool is MerkleTreeWithHistory, IERC20Receiver, ReentrancyGuard, address public immutable multisig; uint256 public lastBalance; - uint256 public minimalWithdrawalAmount; + uint256 public __gap; // storage padding to prevent storage collision uint256 public maximumDepositAmount; mapping(bytes32 => bool) public nullifierHashes; @@ -109,8 +109,8 @@ contract TornadoPool is MerkleTreeWithHistory, IERC20Receiver, ReentrancyGuard, multisig = _multisig; } - function initialize(uint256 _minimalWithdrawalAmount, uint256 _maximumDepositAmount) external initializer { - _configureLimits(_minimalWithdrawalAmount, _maximumDepositAmount); + function initialize(uint256 _maximumDepositAmount) external initializer { + _configureLimits(_maximumDepositAmount); super._initialize(); } @@ -188,8 +188,8 @@ contract TornadoPool is MerkleTreeWithHistory, IERC20Receiver, ReentrancyGuard, } } - function configureLimits(uint256 _minimalWithdrawalAmount, uint256 _maximumDepositAmount) public onlyMultisig { - _configureLimits(_minimalWithdrawalAmount, _maximumDepositAmount); + function configureLimits(uint256 _maximumDepositAmount) public onlyMultisig { + _configureLimits(_maximumDepositAmount); } function calculatePublicAmount(int256 _extAmount, uint256 _fee) public pure returns (uint256) { @@ -275,12 +275,11 @@ contract TornadoPool is MerkleTreeWithHistory, IERC20Receiver, ReentrancyGuard, token.transferAndCall( omniBridge, uint256(-_extData.extAmount), - abi.encodePacked(l1Unwrapper, _extData.recipient, _extData.l1Fee) + abi.encodePacked(l1Unwrapper, abi.encode(_extData.recipient, _extData.l1Fee)) ); } else { token.transfer(_extData.recipient, uint256(-_extData.extAmount)); } - require(uint256(-_extData.extAmount) >= minimalWithdrawalAmount, "amount is less than minimalWithdrawalAmount"); // prevents ddos attack to Bridge } if (_extData.fee > 0) { token.transfer(_extData.relayer, _extData.fee); @@ -295,9 +294,7 @@ contract TornadoPool is MerkleTreeWithHistory, IERC20Receiver, ReentrancyGuard, } } - function _configureLimits(uint256 _minimalWithdrawalAmount, uint256 _maximumDepositAmount) internal { - require(_minimalWithdrawalAmount <= MIN_EXT_AMOUNT_LIMIT, "minimalWithdrawal over limit"); - minimalWithdrawalAmount = _minimalWithdrawalAmount; + function _configureLimits(uint256 _maximumDepositAmount) internal { maximumDepositAmount = _maximumDepositAmount; } } diff --git a/contracts/bridge/L1Unwrapper.sol b/contracts/bridge/L1Unwrapper.sol index 1b3ea62..07491bc 100644 --- a/contracts/bridge/L1Unwrapper.sol +++ b/contracts/bridge/L1Unwrapper.sol @@ -15,7 +15,6 @@ pragma abicoder v2; import "omnibridge/contracts/helpers/WETHOmnibridgeRouter.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; -import { BytesHelper } from "../libraries/Bytes.sol"; /// @dev Extension for original WETHOmnibridgeRouter that stores TornadoPool account registrations. contract L1Unwrapper is WETHOmnibridgeRouter { @@ -88,16 +87,18 @@ contract L1Unwrapper is WETHOmnibridgeRouter { ) external override { require(_token == address(WETH), "only WETH token"); require(msg.sender == address(bridge), "only from bridge address"); - require(_data.length == 52, "incorrect data length"); + require(_data.length == 64, "incorrect data length"); WETH.withdraw(_value); - uint256 l1Fee = BytesHelper.sliceToUint(_data, 20); + (address payable receipient, uint256 l1Fee) = abi.decode(_data, (address, uint256)); - AddressHelper.safeSendValue(payable(BytesHelper.bytesToAddress(_data)), _value.sub(l1Fee)); + AddressHelper.safeSendValue(receipient, _value.sub(l1Fee)); - address payable l1FeeTo = l1FeeReceiver != payable(address(0)) ? l1FeeReceiver : payable(tx.origin); - AddressHelper.safeSendValue(l1FeeTo, l1Fee); + if (l1Fee > 0) { + address payable l1FeeTo = l1FeeReceiver != payable(address(0)) ? l1FeeReceiver : payable(tx.origin); + AddressHelper.safeSendValue(l1FeeTo, l1Fee); + } } /** diff --git a/contracts/libraries/Bytes.sol b/contracts/libraries/Bytes.sol deleted file mode 100644 index 08dc98f..0000000 --- a/contracts/libraries/Bytes.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -/** - * @title Bytes - * @dev Helper methods to transform bytes to other solidity types. - */ -library BytesHelper { - /** - * @dev Truncate bytes array if its size is more than 20 bytes. - * NOTE: This function does not perform any checks on the received parameter. - * Make sure that the _bytes argument has a correct length, not less than 20 bytes. - * A case when _bytes has length less than 20 will lead to the undefined behaviour, - * since assembly will read data from memory that is not related to the _bytes argument. - * @param _bytes to be converted to address type - * @return addr address included in the firsts 20 bytes of the bytes array in parameter. - */ - function bytesToAddress(bytes memory _bytes) internal pure returns (address addr) { - assembly { - addr := mload(add(_bytes, 20)) - } - } - - /** - * @param _bytes it's 32 length slice to be converted to uint type - * @param _start start index of slice - * @return x uint included in the 32 length slice of the bytes array in parameter. - */ - function sliceToUint(bytes memory _bytes, uint256 _start) internal pure returns (uint256 x) { - require(_bytes.length >= _start + 32, "slicing out of range"); - assembly { - x := mload(add(_bytes, add(0x20, _start))) - } - } -} diff --git a/test/full.test.js b/test/full.test.js index a4f65d4..68259a1 100644 --- a/test/full.test.js +++ b/test/full.test.js @@ -14,7 +14,6 @@ const { generate } = require('../src/0_generateAddresses') const MERKLE_TREE_HEIGHT = 5 const l1ChainId = 1 -const MINIMUM_WITHDRAWAL_AMOUNT = utils.parseEther(process.env.MINIMUM_WITHDRAWAL_AMOUNT || '0.05') const MAXIMUM_DEPOSIT_AMOUNT = utils.parseEther(process.env.MAXIMUM_DEPOSIT_AMOUNT || '1') describe('TornadoPool', function () { @@ -69,7 +68,6 @@ describe('TornadoPool', function () { ) const { data } = await tornadoPoolImpl.populateTransaction.initialize( - MINIMUM_WITHDRAWAL_AMOUNT, MAXIMUM_DEPOSIT_AMOUNT, ) const proxy = await deploy( @@ -105,13 +103,11 @@ describe('TornadoPool', function () { it('should configure', async () => { const { tornadoPool, multisig } = await loadFixture(fixture) - const newWithdrawalLimit = utils.parseEther('0.01337') const newDepositLimit = utils.parseEther('1337') - await tornadoPool.connect(multisig).configureLimits(newWithdrawalLimit, newDepositLimit) + await tornadoPool.connect(multisig).configureLimits(newDepositLimit) expect(await tornadoPool.maximumDepositAmount()).to.be.equal(newDepositLimit) - expect(await tornadoPool.minimalWithdrawalAmount()).to.be.equal(newWithdrawalLimit) }) }) @@ -337,7 +333,7 @@ describe('TornadoPool', function () { const fromBlock = await ethers.provider.getBlock() const events = await omniBridge.queryFilter(filter, fromBlock.number) onTokenBridgedData = events[0].args.data - const hexL1Fee = '0x' + events[0].args.data.toString().slice(42) + const hexL1Fee = '0x' + events[0].args.data.toString().slice(66) expect(ethers.BigNumber.from(hexL1Fee)).to.be.equal(l1Fee) const recipientBalance = await token.balanceOf(recipient) @@ -444,7 +440,7 @@ describe('TornadoPool', function () { const fromBlock = await ethers.provider.getBlock() const events = await omniBridge.queryFilter(filter, fromBlock.number) onTokenBridgedData = events[0].args.data - const hexL1Fee = '0x' + events[0].args.data.toString().slice(42) + const hexL1Fee = '0x' + events[0].args.data.toString().slice(66) expect(ethers.BigNumber.from(hexL1Fee)).to.be.equal(l1Fee) const recipientBalance = await token.balanceOf(recipient)