Merge pull request #26 from 0xAyanami/develop

Patch bugs with ERC20 support
This commit is contained in:
Roman Storm 2022-01-27 01:27:02 -08:00 committed by GitHub
commit 542c7c7980
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 53 additions and 45 deletions

98
cli.js
View File

@ -41,17 +41,20 @@ function toHex(number, length = 32) {
} }
/** Display ETH account balance */ /** Display ETH account balance */
async function printETHBalance({ address, name, symbol }) { async function printETHBalance({ address, name }) {
console.log(`${name} balance is`, web3.utils.fromWei(await web3.eth.getBalance(address)),`${symbol}`) const checkBalance = await web3.eth.getBalance(address)
console.log(`${name} balance is`, web3.utils.fromWei(checkBalance),`${netSymbol}`)
} }
/** Display ERC20 account balance */ /** Display ERC20 account balance */
async function printERC20Balance({ address, name, tokenAddress }) { async function printERC20Balance({ address, name, tokenAddress }) {
const erc20ContractJson = require('./build/contracts/ERC20Mock.json') const erc20ContractJson = require('./build/contracts/ERC20Mock.json')
erc20 = tokenAddress ? new web3.eth.Contract(erc20ContractJson.abi, tokenAddress) : erc20 erc20 = tokenAddress ? new web3.eth.Contract(erc20ContractJson.abi, tokenAddress) : erc20
balance = await erc20.methods.balanceOf(address).call() const tokenBalance = await erc20.methods.balanceOf(address).call()
decimals = await erc20.methods.decimals().call() const tokenDecimals = await erc20.methods.decimals().call()
console.log(`${name}`,(await erc20.methods.name().call()),`Token Balance is`,toDecimals(balance, decimals, (balance.length + decimals)).toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ","),(await erc20.methods.symbol().call())) const tokenName = await erc20.methods.name().call()
const tokenSymbol = await erc20.methods.symbol().call()
console.log(`${name}`,tokenName,`Token Balance is`,toDecimals(tokenBalance, tokenDecimals, (tokenBalance.length + tokenDecimals)).toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ","),tokenSymbol)
} }
async function generateTransaction(to, encodedData, value = 0) { async function generateTransaction(to, encodedData, value = 0) {
@ -159,13 +162,13 @@ async function deposit({ currency, amount }) {
console.log(`Your note: ${noteString}`) console.log(`Your note: ${noteString}`)
await backupNote({ currency, amount, netId, note, noteString }) await backupNote({ currency, amount, netId, note, noteString })
if (currency === netSymbol.toLowerCase()) { if (currency === netSymbol.toLowerCase()) {
await printETHBalance({ address: tornadoContract._address, name: 'Tornado contract', symbol: currency.toUpperCase() }) await printETHBalance({ address: tornadoContract._address, name: 'Tornado contract' })
await printETHBalance({ address: senderAccount, name: 'Sender account', symbol: currency.toUpperCase() }) await printETHBalance({ address: senderAccount, name: 'Sender account' })
const value = isLocalRPC ? ETH_AMOUNT : fromDecimals({ amount, decimals: 18 }) const value = isLocalRPC ? ETH_AMOUNT : fromDecimals({ amount, decimals: 18 })
console.log('Submitting deposit transaction') console.log('Submitting deposit transaction')
await generateTransaction(contractAddress, await tornado.methods.deposit(tornadoInstance, toHex(deposit.commitment), []).encodeABI(), value) await generateTransaction(contractAddress, tornado.methods.deposit(tornadoInstance, toHex(deposit.commitment), []).encodeABI(), value)
await printETHBalance({ address: tornadoContract._address, name: 'Tornado contract', symbol: currency.toUpperCase() }) await printETHBalance({ address: tornadoContract._address, name: 'Tornado contract' })
await printETHBalance({ address: senderAccount, name: 'Sender account', symbol: currency.toUpperCase() }) await printETHBalance({ address: senderAccount, name: 'Sender account' })
} else { } else {
// a token // a token
await printERC20Balance({ address: tornadoContract._address, name: 'Tornado contract' }) await printERC20Balance({ address: tornadoContract._address, name: 'Tornado contract' })
@ -174,18 +177,18 @@ async function deposit({ currency, amount }) {
const tokenAmount = isLocalRPC ? TOKEN_AMOUNT : fromDecimals({ amount, decimals }) const tokenAmount = isLocalRPC ? TOKEN_AMOUNT : fromDecimals({ amount, decimals })
if (isLocalRPC) { if (isLocalRPC) {
console.log('Minting some test tokens to deposit') console.log('Minting some test tokens to deposit')
await generateTransaction(erc20Address, await erc20.methods.mint(senderAccount, tokenAmount).encodeABI()) await generateTransaction(erc20Address, erc20.methods.mint(senderAccount, tokenAmount).encodeABI())
} }
const allowance = await erc20.methods.allowance(senderAccount, tornado._address).call({ from: senderAccount }) const allowance = await erc20.methods.allowance(senderAccount, tornado._address).call({ from: senderAccount })
console.log('Current allowance is', fromWei(allowance)) console.log('Current allowance is', fromWei(allowance))
if (toBN(allowance).lt(toBN(tokenAmount))) { if (toBN(allowance).lt(toBN(tokenAmount))) {
console.log('Approving tokens for deposit') console.log('Approving tokens for deposit')
await generateTransaction(erc20Address, await erc20.methods.approve(tornado._address, tokenAmount).encodeABI()) await generateTransaction(erc20Address, erc20.methods.approve(tornado._address, tokenAmount).encodeABI())
} }
console.log('Submitting deposit transaction') console.log('Submitting deposit transaction')
await generateTransaction(contractAddress, await tornado.methods.deposit(toHex(deposit.commitment)).encodeABI()) await generateTransaction(contractAddress, tornado.methods.deposit(toHex(deposit.commitment)).encodeABI())
await printERC20Balance({ address: tornadoContract._address, name: 'Tornado contract' }) await printERC20Balance({ address: tornadoContract._address, name: 'Tornado contract' })
await printERC20Balance({ address: senderAccount, name: 'Sender account' }) await printERC20Balance({ address: senderAccount, name: 'Sender account' })
} }
@ -341,13 +344,19 @@ async function withdraw({ deposit, currency, amount, recipient, relayerURL, torP
// using private key // using private key
// check if the address of recepient matches with the account of provided private key from environment to prevent accidental use of deposit address for withdrawal transaction. // check if the address of recepient matches with the account of provided private key from environment to prevent accidental use of deposit address for withdrawal transaction.
const { address } = await web3.eth.accounts.privateKeyToAccount('0x' + PRIVATE_KEY) assert(recipient.toLowerCase() == senderAccount.toLowerCase(), 'Withdrawal recepient mismatches with the account of provided private key from environment file')
assert(recipient.toLowerCase() == address.toLowerCase(), 'Withdrawal amount recepient mismatches with the account of provided private key from environment file') const checkBalance = await web3.eth.getBalance(senderAccount)
assert(checkBalance !== 0, 'You have 0 balance, make sure to fund account by withdrawing from tornado using relayer first')
const { proof, args } = await generateProof({ deposit, currency, amount, recipient, refund }) const { proof, args } = await generateProof({ deposit, currency, amount, recipient, refund })
console.log('Submitting withdraw transaction') console.log('Submitting withdraw transaction')
await generateTransaction(contractAddress, await tornado.methods.withdraw(tornadoInstance, proof, ...args).encodeABI()) await generateTransaction(contractAddress, tornado.methods.withdraw(tornadoInstance, proof, ...args).encodeABI())
}
if (currency === netSymbol.toLowerCase()) {
await printETHBalance({ address: recipient, name: 'Recipient' })
} else {
await printERC20Balance({ address: recipient, name: 'Recipient' })
} }
console.log('Done withdrawal from Tornado Cash') console.log('Done withdrawal from Tornado Cash')
} }
@ -364,38 +373,39 @@ async function send({ address, amount, tokenAddress }) {
if (tokenAddress) { if (tokenAddress) {
const erc20ContractJson = require('./build/contracts/ERC20Mock.json') const erc20ContractJson = require('./build/contracts/ERC20Mock.json')
erc20 = new web3.eth.Contract(erc20ContractJson.abi, tokenAddress) erc20 = new web3.eth.Contract(erc20ContractJson.abi, tokenAddress)
const balance = await erc20.methods.balanceOf(senderAccount).call() const tokenBalance = await erc20.methods.balanceOf(senderAccount).call()
const decimals = await erc20.methods.decimals().call() const tokenDecimals = await erc20.methods.decimals().call()
const toSend = amount * Math.pow(10, decimals) const tokenSymbol = await erc20.methods.symbol().call()
if (balance < toSend) { const toSend = amount * Math.pow(10, tokenDecimals)
console.error("You have",toDecimals(balance, decimals, (balance.length + decimals)).toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ","),(await erc20.methods.symbol().call()),", you can't send more than you have") if (tokenBalance < toSend) {
console.error("You have",toDecimals(tokenBalance, tokenDecimals, (tokenBalance.length + tokenDecimals)).toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ","),tokenSymbol,", you can't send more than you have")
process.exit(1); process.exit(1);
} }
await generateTransaction(tokenAddress, await erc20.methods.transfer(address, toBN(toSend)).encodeABI()) const encodeTransfer = erc20.methods.transfer(address, toBN(toSend)).encodeABI()
console.log('Sent',amount,(await erc20.methods.symbol().call()),'to',address); await generateTransaction(tokenAddress, encodeTransfer)
console.log('Sent',amount,tokenSymbol,'to',address);
} else { } else {
const balance = await web3.eth.getBalance(senderAccount) const balance = await web3.eth.getBalance(senderAccount)
if (balance == 0) { assert(balance !== 0, "You have 0 balance, can't send transaction")
console.error("You have 0 balance, can't send") if (amount) {
process.exit(1); toSend = amount * Math.pow(10, 18)
} if (balance < toSend) {
if (!amount) { console.error("You have",web3.utils.fromWei(toHex(balance)),netSymbol+", you can't send more than you have.")
process.exit(1);
}
} else {
console.log('Amount not defined, sending all available amounts') console.log('Amount not defined, sending all available amounts')
const gasPrice = await fetchGasPrice() const gasPrice = await fetchGasPrice()
const gasLimit = 21000; const gasLimit = 21000;
if (netId == 1 || netId == 5) { if (netId == 1 || netId == 5) {
const priorityFee = await gasPrices(3) const priorityFee = await gasPrices(3)
amount = (balance - (gasLimit * (parseInt(gasPrice) + parseInt(priorityFee)))) toSend = (balance - (gasLimit * (parseInt(gasPrice) + parseInt(priorityFee))))
} else { } else {
amount = (balance - (gasLimit * parseInt(gasPrice))) toSend = (balance - (gasLimit * parseInt(gasPrice)))
} }
} }
if (balance < amount) { await generateTransaction(address, null, toSend)
console.error("You have",web3.utils.fromWei(toHex(balance)),netSymbol,", you can't send more than you have.") console.log('Sent',web3.utils.fromWei(toHex(toSend)),netSymbol,'to',address);
process.exit(1);
}
await generateTransaction(address, null, amount)
console.log('Sent',web3.utils.fromWei(toHex(amount)),netSymbol,'to',address);
} }
} }
@ -724,7 +734,7 @@ async function fetchEvents({ type, currency, amount}) {
await tornadoContract.getPastEvents(capitalizeFirstLetter(type), { await tornadoContract.getPastEvents(capitalizeFirstLetter(type), {
fromBlock: i, fromBlock: i,
toBlock: i+chunks-1, toBlock: i+chunks-1,
}).then(r => { fetchedEvents = fetchedEvents.concat(r); console.log("Fetched",amount,currency.toUpperCase(),type,"events to block:", i) }, err => { console.error(i + " failed fetching",type,"events from node", err); process.exit(1); }).catch(console.log); }).then(r => { fetchedEvents = fetchedEvents.concat(r); console.log("Fetched",amount,currency.toUpperCase(),type,"events to block:", i+chunks-1) }, err => { console.error(i + " failed fetching",type,"events from node", err); process.exit(1); }).catch(console.log);
} }
async function mapDepositEvents() { async function mapDepositEvents() {
@ -943,6 +953,7 @@ async function init({ rpc, noteNetId, currency = 'dai', amount = '100', torPort,
groth16 = await buildGroth16() groth16 = await buildGroth16()
netId = await web3.eth.net.getId() netId = await web3.eth.net.getId()
netName = getCurrentNetworkName() netName = getCurrentNetworkName()
netSymbol = getCurrentNetworkSymbol()
if (noteNetId && Number(noteNetId) !== netId) { if (noteNetId && Number(noteNetId) !== netId) {
throw new Error('This note is for a different network. Specify the --rpc option explicitly') throw new Error('This note is for a different network. Specify the --rpc option explicitly')
} }
@ -951,15 +962,13 @@ async function init({ rpc, noteNetId, currency = 'dai', amount = '100', torPort,
} }
if (isLocalRPC) { if (isLocalRPC) {
tornadoAddress = currency === 'eth' ? contractJson.networks[netId].address : erc20tornadoJson.networks[netId].address tornadoAddress = currency === netSymbol.toLowerCase() ? contractJson.networks[netId].address : erc20tornadoJson.networks[netId].address
tokenAddress = currency !== 'eth' ? erc20ContractJson.networks[netId].address : null tokenAddress = currency !== netSymbol.toLowerCase() ? erc20ContractJson.networks[netId].address : null
netSymbol = getCurrentNetworkSymbol()
deployedBlockNumber = 0 deployedBlockNumber = 0
senderAccount = (await web3.eth.getAccounts())[0] senderAccount = (await web3.eth.getAccounts())[0]
} else { } else {
try { try {
if (balanceCheck) { if (balanceCheck) {
netSymbol = getCurrentNetworkSymbol()
currency = netSymbol.toLowerCase() currency = netSymbol.toLowerCase()
amount = Object.keys(config.deployments[`netId${netId}`][currency].instanceAddress)[0] amount = Object.keys(config.deployments[`netId${netId}`][currency].instanceAddress)[0]
} }
@ -970,17 +979,16 @@ async function init({ rpc, noteNetId, currency = 'dai', amount = '100', torPort,
if (!tornadoAddress) { if (!tornadoAddress) {
throw new Error() throw new Error()
} }
tokenAddress = config.deployments[`netId${netId}`][currency].tokenAddress tokenAddress = currency !== netSymbol.toLowerCase() ? config.deployments[`netId${netId}`][currency].tokenAddress : null
} catch (e) { } catch (e) {
console.error('There is no such tornado instance, check the currency and amount you provide', e) console.error('There is no such tornado instance, check the currency and amount you provide', e)
process.exit(1) process.exit(1)
} }
} }
netSymbol = getCurrentNetworkSymbol()
tornado = new web3.eth.Contract(contractJson, tornadoAddress) tornado = new web3.eth.Contract(contractJson, tornadoAddress)
tornadoContract = new web3.eth.Contract(instanceJson, tornadoInstance) tornadoContract = new web3.eth.Contract(instanceJson, tornadoInstance)
contractAddress = tornadoAddress contractAddress = tornadoAddress
erc20 = currency !== 'eth' ? new web3.eth.Contract(erc20ContractJson.abi, tokenAddress) : {} erc20 = currency !== netSymbol.toLowerCase() ? new web3.eth.Contract(erc20ContractJson.abi, tokenAddress) : {}
erc20Address = tokenAddress erc20Address = tokenAddress
} }
@ -1041,7 +1049,7 @@ async function main() {
console.log("Using address",senderAccount,"from private key") console.log("Using address",senderAccount,"from private key")
address = senderAccount; address = senderAccount;
} }
await printETHBalance({ address, name: 'Account', symbol: netSymbol }) await printETHBalance({ address, name: 'Account' })
if (tokenAddress) { if (tokenAddress) {
await printERC20Balance({ address, name: 'Account', tokenAddress }) await printERC20Balance({ address, name: 'Account', tokenAddress })
} }