Skip to content

Instantly share code, notes, and snippets.

@hakymulla
Last active March 14, 2022 05:54
Show Gist options
  • Save hakymulla/199936f73a577da50e5ba3b693cc84bc to your computer and use it in GitHub Desktop.
Save hakymulla/199936f73a577da50e5ba3b693cc84bc to your computer and use it in GitHub Desktop.
Add a script named custom.test.js
const hre = require('hardhat')
const { ethers, waffle } = hre
const { loadFixture } = waffle
const { expect } = require('chai')
const { poseidonHash2, toFixedHex } = require('../src/utils')
const MERKLE_TREE_HEIGHT = 5
const MerkleTree = require('fixed-merkle-tree')
const { utils } = ethers
const Utxo = require('../src/utxo')
const { transaction, registerAndTransact, prepareTransaction, buildMerkleTree } = require('../src/index')
const { Keypair } = require('../src/keypair')
const { encodeDataForBridge } = require('./utils')
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('Question 2 Test', function () {
this.timeout(20000)
async function deploy(contractName, ...args) {
const Factory = await ethers.getContractFactory(contractName)
const instance = await Factory.deploy(...args)
return instance.deployed()
}
async function fixture() {
require('../scripts/compileHasher')
const [sender, gov, l1Unwrapper, multisig] = await ethers.getSigners()
const verifier2 = await deploy('Verifier2')
const verifier16 = await deploy('Verifier16')
const hasher = await deploy('Hasher')
const merkleTreeWithHistory = await deploy(
'MerkleTreeWithHistoryMock',
MERKLE_TREE_HEIGHT,
hasher.address,
)
await merkleTreeWithHistory.initialize()
const token = await deploy('PermittableToken', 'Wrapped ETH', 'WETH', 18, l1ChainId)
await token.mint(sender.address, utils.parseEther('10000'))
const amb = await deploy('MockAMB', gov.address, l1ChainId)
const omniBridge = await deploy('MockOmniBridge', amb.address)
/** @type {TornadoPool} */
const tornadoPoolImpl = await deploy(
'TornadoPool',
verifier2.address,
verifier16.address,
MERKLE_TREE_HEIGHT,
hasher.address,
token.address,
omniBridge.address,
l1Unwrapper.address,
gov.address,
l1ChainId,
multisig.address,
)
const { data } = await tornadoPoolImpl.populateTransaction.initialize(
MINIMUM_WITHDRAWAL_AMOUNT,
MAXIMUM_DEPOSIT_AMOUNT,
)
const proxy = await deploy(
'CrossChainUpgradeableProxy',
tornadoPoolImpl.address,
gov.address,
data,
amb.address,
l1ChainId,
)
const tornadoPool = tornadoPoolImpl.attach(proxy.address)
await token.approve(tornadoPool.address, utils.parseEther('10000'))
return { tornadoPool, token, proxy, omniBridge, amb, gov, multisig,hasher, merkleTreeWithHistory }
}
it('should deposit from L1 and withdraw to L2 Question 2', async function () {
const { merkleTreeWithHistory, tornadoPool, token, omniBridge } = await loadFixture(fixture)
const gas = await merkleTreeWithHistory.estimateGas.insert(toFixedHex(123), toFixedHex(456))
console.log('gas needed to insert a pair of leaves', gas - 21000)
const aliceKeypair = new Keypair() // contains private and public keys
// Alice deposits into tornado pool
const aliceDepositAmount = utils.parseEther('0.08')
const aliceDepositUtxo = new Utxo({ amount: aliceDepositAmount, keypair: aliceKeypair })
const { args, extData } = await prepareTransaction({
tornadoPool,
outputs: [aliceDepositUtxo],
})
const onTokenBridgedData = encodeDataForBridge({
proof: args,
extData,
})
const onTokenBridgedTx = await tornadoPool.populateTransaction.onTokenBridged(
token.address,
aliceDepositUtxo.amount,
onTokenBridgedData,
)
// emulating bridge. first it sends tokens to omnibridge mock then it sends to the pool
await token.transfer(omniBridge.address, aliceDepositAmount)
const transferTx = await token.populateTransaction.transfer(tornadoPool.address, aliceDepositAmount)
await omniBridge.execute([
{ who: token.address, callData: transferTx.data }, // send tokens to pool
{ who: tornadoPool.address, callData: onTokenBridgedTx.data }, // call onTokenBridgedTx
])
// Alice withdraws a part of his funds from the shielded pool
const aliceWithdrawAmount = utils.parseEther('0.05')
const AliceEthAddress = '0xDeaD00000000000000000000000000000000BEEf'
const aliceChangeUtxo = new Utxo({
amount: aliceDepositAmount.sub(aliceWithdrawAmount),
keypair: aliceKeypair,
})
await transaction({
tornadoPool,
inputs: [aliceDepositUtxo],
outputs: [aliceChangeUtxo],
recipient: AliceEthAddress,
isL1Withdrawal: false
})
const AliceEthAddressBalance = await token.balanceOf(AliceEthAddress)
console.log("AliceEthAddressBalance ", ethers.utils.formatEther(AliceEthAddressBalance))
expect(AliceEthAddressBalance).to.be.equal(aliceWithdrawAmount)
const omniBridgeBalance = await token.balanceOf(omniBridge.address)
console.log("omniBridgeBalance ", ethers.utils.formatEther(omniBridgeBalance))
expect(omniBridgeBalance).to.be.equal(0)
const tornadoPoolBalance = await token.balanceOf(tornadoPool.address)
console.log("tornadoPoolBalance ", ethers.utils.formatEther(tornadoPoolBalance))
expect(tornadoPoolBalance).to.be.equal(aliceDepositAmount.sub(aliceWithdrawAmount))
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment