Merge branch 'xdai' into onchain-tree

This commit is contained in:
Alexey 2021-09-29 19:41:56 +03:00
commit c2c3064601

View File

@ -20,17 +20,26 @@ interface IVerifier {
function verifyProof(bytes memory _proof, uint256[21] memory _input) external view returns (bool); function verifyProof(bytes memory _proof, uint256[21] memory _input) external view returns (bool);
} }
interface ERC20 { interface IERC20 {
function transfer(address to, uint256 value) external returns (bool); function transfer(address to, uint256 value) external returns (bool);
} }
contract TornadoPool is MerkleTreeWithHistory { interface IERC20Receiver {
function onTokenBridged(
IERC20 token,
uint256 value,
bytes calldata data
) external;
}
contract TornadoPool is MerkleTreeWithHistory, IERC20Receiver {
int256 public constant MAX_EXT_AMOUNT = 2**248; int256 public constant MAX_EXT_AMOUNT = 2**248;
uint256 public constant MAX_FEE = 2**248; uint256 public constant MAX_FEE = 2**248;
mapping(bytes32 => bool) public nullifierHashes; mapping(bytes32 => bool) public nullifierHashes;
IVerifier public immutable verifier2; IVerifier public immutable verifier2;
IVerifier public immutable verifier16; IVerifier public immutable verifier16;
IERC20 public immutable token;
struct ExtData { struct ExtData {
address payable recipient; address payable recipient;
@ -69,13 +78,15 @@ contract TornadoPool is MerkleTreeWithHistory {
IVerifier _verifier2, IVerifier _verifier2,
IVerifier _verifier16, IVerifier _verifier16,
uint32 _levels, uint32 _levels,
address _hasher address _hasher,
IERC20 _token
) MerkleTreeWithHistory(_levels, _hasher) { ) MerkleTreeWithHistory(_levels, _hasher) {
verifier2 = _verifier2; verifier2 = _verifier2;
verifier16 = _verifier16; verifier16 = _verifier16;
token = _token;
} }
function transaction(Proof calldata _args, ExtData calldata _extData) public payable { function transaction(Proof memory _args, ExtData memory _extData) public payable {
require(isKnownRoot(_args.root), "Invalid merkle root"); require(isKnownRoot(_args.root), "Invalid merkle root");
for (uint256 i = 0; i < _args.inputNullifiers.length; i++) { for (uint256 i = 0; i < _args.inputNullifiers.length; i++) {
require(!isSpent(_args.inputNullifiers[i]), "Input is already spent"); require(!isSpent(_args.inputNullifiers[i]), "Input is already spent");
@ -93,13 +104,13 @@ contract TornadoPool is MerkleTreeWithHistory {
} else if (_extData.extAmount < 0) { } else if (_extData.extAmount < 0) {
require(msg.value == 0, "Sent ETH amount should be 0 for withdrawal"); require(msg.value == 0, "Sent ETH amount should be 0 for withdrawal");
require(_extData.recipient != address(0), "Can't withdraw to zero address"); require(_extData.recipient != address(0), "Can't withdraw to zero address");
_transfer(_extData.recipient, uint256(-_extData.extAmount)); token.transfer(_extData.recipient, uint256(-_extData.extAmount));
} else { } else {
require(msg.value == 0, "Sent ETH amount should be 0 for transaction"); require(msg.value == 0, "Sent ETH amount should be 0 for transaction");
} }
if (_extData.fee > 0) { if (_extData.fee > 0) {
_transfer(_extData.relayer, _extData.fee); token.transfer(_extData.relayer, _extData.fee);
} }
_insert(_args.outputCommitments[0], _args.outputCommitments[1]); _insert(_args.outputCommitments[0], _args.outputCommitments[1]);
@ -110,18 +121,6 @@ contract TornadoPool is MerkleTreeWithHistory {
} }
} }
function _transfer(address payable _to, uint256 _amount) internal {
uint256 id;
assembly {
id := chainid()
}
if (id == 10) {
ERC20(0x4200000000000000000000000000000000000006).transfer(_to, _amount);
} else {
_to.transfer(_amount);
}
}
function calculatePublicAmount(int256 _extAmount, uint256 _fee) public pure returns (uint256) { function calculatePublicAmount(int256 _extAmount, uint256 _fee) public pure returns (uint256) {
require(_fee < MAX_FEE, "Invalid fee"); require(_fee < MAX_FEE, "Invalid fee");
require(_extAmount > -MAX_EXT_AMOUNT && _extAmount < MAX_EXT_AMOUNT, "Invalid ext amount"); require(_extAmount > -MAX_EXT_AMOUNT && _extAmount < MAX_EXT_AMOUNT, "Invalid ext amount");
@ -134,7 +133,7 @@ contract TornadoPool is MerkleTreeWithHistory {
return nullifierHashes[_nullifierHash]; return nullifierHashes[_nullifierHash];
} }
function verifyProof(Proof calldata _args) public view returns (bool) { function verifyProof(Proof memory _args) public view returns (bool) {
if (_args.inputNullifiers.length == 2) { if (_args.inputNullifiers.length == 2) {
return return
verifier2.verifyProof( verifier2.verifyProof(
@ -182,17 +181,31 @@ contract TornadoPool is MerkleTreeWithHistory {
} }
} }
function register(Register calldata args) public { function register(Register memory args) public {
emit PublicKey(msg.sender, args.pubKey); emit PublicKey(msg.sender, args.pubKey);
emit EncryptedAccount(msg.sender, args.account); emit EncryptedAccount(msg.sender, args.account);
} }
function registerAndTransact( function registerAndTransact(
Register calldata _registerArgs, Register memory _registerArgs,
Proof calldata _proofArgs, Proof memory _proofArgs,
ExtData calldata _extData ExtData memory _extData
) external payable { ) public payable {
register(_registerArgs); register(_registerArgs);
transaction(_proofArgs, _extData); transaction(_proofArgs, _extData);
} }
function onTokenBridged(
IERC20 _token,
uint256,
bytes calldata _data
) external override {
require(_token == token, "provided token is not supported");
(Register memory _registerArgs, Proof memory _args, ExtData memory _extData) = abi.decode(_data, (Register, Proof, ExtData));
if (_registerArgs.pubKey.length != 0 && _registerArgs.account.length != 0) {
registerAndTransact(_registerArgs, _args, _extData);
} else {
transaction(_args, _extData);
}
}
} }