[英]VM Exception while processing transaction: revert TransferHelper: TRANSFER_FROM_FAILED when running manipulatePrice.js test for bot.js
I am using the code from Dapp Unversity's trading bot masterclass to try to create a bot that will scan cryptocurrency decentralized exchanges for price differences in token pairs and then execute a smart contract to use a flash loan to profit off of this.我正在使用 Dapp 大学的交易机器人大师班的代码来尝试创建一个机器人,该机器人将扫描加密货币去中心化交易所以获取代币对的价格差异,然后执行智能合约以使用 flash 贷款从中获利。 When testing, I am able to see run a ganache-cli node and run my scanning bot to listen for swap opportunities on ganache.
测试时,我能够看到运行一个 ganache-cli 节点并运行我的扫描机器人以侦听 ganache 上的交换机会。 There is a script designed to create a swap opportunity by swapping a large amount of SHIB for WETH on the test.net to see if the smart contract will deploy and execute when a swap opportunity is detected by the bot.
有一个脚本旨在通过在 test.net 上将大量 SHIB 换成 WETH 来创建交换机会,以查看智能合约是否会在机器人检测到交换机会时部署和执行。 However, running this script yields the error
但是,运行此脚本会产生错误
UnhandledPromiseRejectionWarning: Error: Returned error: VM Exception while processing transaction: revert TransferHelper: TRANSFER_FROM_FAILED
UnhandledPromiseRejectionWarning:错误:返回错误:处理事务时出现VM异常:还原TransferHelper:TRANSFER_FROM_FAILED
Also, in the ganache-cli terminal, I get:此外,在 ganache-cli 终端中,我得到:
Runtime Error: revert Revert reason: TransferHelper: TRANSFER_FROM_FAILED
运行时错误:还原还原原因:TransferHelper:TRANSFER_FROM_FAILED
Here are the commands I run to get to the points above: First, I successfully run ganache-cli -f wss://eth-mai.net.alchemyapi.io/v2/<Your-App-Key> -u 0x0e5069514a3dd613350bab01b58fd850058e5ca4 -p 7545
with my app key.以下是我为达到上述目的而运行的命令:首先,我成功运行了
ganache-cli -f wss://eth-mai.net.alchemyapi.io/v2/<Your-App-Key> -u 0x0e5069514a3dd613350bab01b58fd850058e5ca4 -p 7545
与我的应用程序密钥。 Then, I successfully run node bot.js
in another terminal to scan for swap opportunities on ganache.然后,我在另一个终端成功运行了
node bot.js
来扫描 ganache 上的交换机会。 Finally, I run node scripts\manipulatePrice.JS
which outputs "Beginnig Swap... Input token: SHIB Output token: WETH" before outputting the above error.最后,我运行
node scripts\manipulatePrice.JS
,输出“Beginnig Swap... Input token: SHIB Output token: WETH”,然后输出上述错误。
I have tried using node --trace-warnings
to show where the warning was created, but was led nowhere helpful.我尝试使用
node --trace-warnings
来显示警告的创建位置,但没有任何帮助。 I am wondering if it has something to do with the Runtime Error: revert message?我想知道它是否与运行时错误有关:还原消息? Below is the code for the manipulatePrice.js script I am trying to run to test my bot.
下面是我试图运行以测试我的机器人的 manipulatePrice.js 脚本的代码。 I can attach more code if need be, but don't want to post too much.
如果需要,我可以附加更多代码,但不想发布太多。 If anyone has insight as to what or where the issue might be, I would greatly appreciate it!!
如果有人知道问题出在哪里或出在哪里,我将不胜感激!!
require("dotenv").config();
const Web3 = require('web3')
const {
ChainId,
Token,
WETH
} = require("@uniswap/sdk")
const IUniswapV2Router02 = require('@uniswap/v2-periphery/build/IUniswapV2Router02.json')
const IUniswapV2Factory = require("@uniswap/v2-core/build/IUniswapV2Factory.json")
const IERC20 = require('@openzeppelin/contracts/build/contracts/ERC20.json')
// -- SETUP NETWORK & WEB3 -- //
const chainId = ChainId.MAINNET
const web3 = new Web3('http://127.0.0.1:7545')
// -- IMPORT HELPER FUNCTIONS -- //
const { getPairContract, calculatePrice } = require('../helpers/helpers')
// -- IMPORT & SETUP UNISWAP/SUSHISWAP CONTRACTS -- //
const config = require('../config.json')
const uFactory = new web3.eth.Contract(IUniswapV2Factory.abi, config.UNISWAP.FACTORY_ADDRESS) // UNISWAP FACTORY CONTRACT
const sFactory = new web3.eth.Contract(IUniswapV2Factory.abi, config.SUSHISWAP.FACTORY_ADDRESS) // SUSHISWAP FACTORY CONTRACT
const uRouter = new web3.eth.Contract(IUniswapV2Router02.abi, config.UNISWAP.V2_ROUTER_02_ADDRESS) // UNISWAP ROUTER CONTRACT
const sRouter = new web3.eth.Contract(IUniswapV2Router02.abi, config.SUSHISWAP.V2_ROUTER_02_ADDRESS) // UNISWAP ROUTER CONTRACT
// -- CONFIGURE VALUES HERE -- //
const V2_FACTORY_TO_USE = uFactory
const V2_ROUTER_TO_USE = uRouter
const UNLOCKED_ACCOUNT = '0x0e5069514a3Dd613350BAB01B58FD850058E5ca4' // SHIB Unlocked Account
const ERC20_ADDRESS = process.env.ARB_AGAINST
const AMOUNT = '40500000000000' // 40,500,000,000,000 SHIB -- Tokens will automatically be converted to wei
const GAS = 450000
// -- SETUP ERC20 CONTRACT & TOKEN -- //
const ERC20_CONTRACT = new web3.eth.Contract(IERC20.abi, ERC20_ADDRESS)
const WETH_CONTRACT = new web3.eth.Contract(IERC20.abi, WETH[chainId].address)
// -- MAIN SCRIPT -- //
const main = async () => {
const accounts = await web3.eth.getAccounts()
const account = accounts[1] // This will be the account to recieve WETH after we perform the swap to manipulate price
const pairContract = await getPairContract(V2_FACTORY_TO_USE, ERC20_ADDRESS, WETH[chainId].address)
const token = new Token(
ChainId.MAINNET,
ERC20_ADDRESS,
18,
await ERC20_CONTRACT.methods.symbol().call(),
await ERC20_CONTRACT.methods.name().call()
)
// Fetch price of SHIB/WETH before we execute the swap
const priceBefore = await calculatePrice(pairContract)
await manipulatePrice(token, account)
// Fetch price of SHIB/WETH after the swap
const priceAfter = await calculatePrice(pairContract)
const data = {
'Price Before': `1 ${WETH[chainId].symbol} = ${Number(priceBefore).toFixed(0)} ${token.symbol}`,
'Price After': `1 ${WETH[chainId].symbol} = ${Number(priceAfter).toFixed(0)} ${token.symbol}`,
}
console.table(data)
let balance = await WETH_CONTRACT.methods.balanceOf(account).call()
balance = web3.utils.fromWei(balance.toString(), 'ether')
console.log(`\nBalance in reciever account: ${balance} WETH\n`)
}
main()
//
async function manipulatePrice(token, account) {
console.log(`\nBeginning Swap...\n`)
console.log(`Input Token: ${token.symbol}`)
console.log(`Output Token: ${WETH[chainId].symbol}\n`)
const amountIn = new web3.utils.BN(
web3.utils.toWei(AMOUNT, 'ether')
)
const path = [token.address, WETH[chainId].address]
const deadline = Math.floor(Date.now() / 1000) + 60 * 20 // 20 minutes
await ERC20_CONTRACT.methods.approve(V2_ROUTER_TO_USE._address, amountIn).send({ from: UNLOCKED_ACCOUNT })
const receipt = await V2_ROUTER_TO_USE.methods.swapExactTokensForTokens(amountIn, 0, path, account, deadline).send({ from: UNLOCKED_ACCOUNT, gas: GAS });
console.log(`Swap Complete!\n`)
return receipt
}
I ran into this issue for the same bot myself and I found the solution.我自己遇到了同一个机器人的这个问题,我找到了解决方案。 Instead of using
.send
you should use .sendSignedTransaction
and sign it yourself with the correct parameters.而不是使用
.send
你应该使用.sendSignedTransaction
并用正确的参数自己签名。 BUT if you are sending from an unlocked account, then use ethers.js to get a signer without knowing the private key!但是,如果您从未锁定的帐户发送,请使用 ethers.js 在不知道私钥的情况下获得签名者!
So, you should replace所以,你应该更换
await ERC20_CONTRACT.methods.approve(V2_ROUTER_TO_USE._address, amountIn).send({ from: UNLOCKED_ACCOUNT })
const receipt = await V2_ROUTER_TO_USE.methods.swapExactTokensForTokens(amountIn, 0, path, account, deadline).send({ from: UNLOCKED_ACCOUNT, gas: GAS });
With this ethers.js alternative有了这个 ethers.js 替代品
const { ethers } = require("ethers")
const provider = new ethers.providers.JsonRpcProvider("http://127.0.0.1:8545")
const signer = provider.getSigner(UNLOCKED_ACCOUNT)
console.log(provider.chainId)
/*
Define the above code at the top,
Then put the rest of your code here,
Then use this for the ethers transaction
*/
const approvalReceiptEthers = await signer.sendTransaction({
from: UNLOCKED_ACCOUNT,
to: ERC20_CONTRACT._address,
data: ERC20_CONTRACT.methods.approve(V2_ROUTER_TO_USE._address, web3.utils.fromWei(amountIn).toString()).encodeABI(),
gasLimit: GAS
})
/*
* Verify that your unlocked account is allowed to use the funds
*/
var allowance = await ERC20_CONTRACT.methods.allowance(UNLOCKED_ACCOUNT, V2_ROUTER_TO_USE._address).call()
console.log("ALLOWANCE:\t\t", web3.utils.fromWei(allowance).toString(), 'ether')
console.log("ATTEMPTED AMOUNT:\t", web3.utils.fromWei(amountIn).toString(), 'ether')
const swapReceiptEthers = await signer.sendTransaction({
from: UNLOCKED_ACCOUNT,
to: V2_ROUTER_TO_USE._address,
data: V2_ROUTER_TO_USE.methods.swapExactTokensForTokens(web3.utils.fromWei(amountIn).toString(), 0, path, account, deadline).encodeABI(),
gasLimit: GAS
}).then(console.log)
Note: the following code, will only work provided that you signed the transaction with THE SENDER'S PRIVATE KEY.注意:以下代码仅在您使用发件人的私钥签署交易时才有效。 So, if you are sending a transaction on behalf of your own account, use this code (presumably for bot.js)
因此,如果您代表自己的帐户发送交易,请使用此代码(大概用于 bot.js)
const approvalTransaction = {
'from' : 'your account address here',
'to' : ERC20_CONTRACT._address,
'data' : ERC20_CONTRACT.methods.approve(V2_ROUTER_TO_USE._address, web3.utils.fromWei(amountIn).toString()).encodeABI(),
'gas' : GAS
}
const transaction = {
'from' : 'your account address here',
'to' : V2_ROUTER_TO_USE._address,
'data' : V2_ROUTER_TO_USE.methods.swapExactTokensForTokens(web3.utils.fromWei(amountIn).toString(), 0, path, account, deadline).encodeABI(),
'gas' : GAS
}
const signedApprovalTx = await web3.eth.accounts.signTransaction(approvalTransaction, process.env.DEPLOYMENT_ACCOUNT_KEY, )
const signedTx = await web3.eth.accounts.signTransaction(transaction, process.env.DEPLOYMENT_ACCOUNT_KEY)
await web3.eth.sendSignedTransaction(signedApprovalTx.rawTransaction)
const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction)
NOTE : For those of you following the same Trading Bot masterclass, this same logic applies to the bot.js
code as well when you execute your trade..注意:对于那些学习相同 Trading Bot 大师班的人来说,同样的逻辑也适用于
bot.js
代码,当您执行交易时。
SUMMARY: If you are sending a signed transaction using an unlocked account with ganache-cli, you will need to use ethers.js to sign the message without knowing the private key.摘要:如果您使用带有 ganache-cli 的解锁帐户发送签名交易,您将需要使用 ethers.js 在不知道私钥的情况下对消息进行签名。 Otherwise if you are sending a signed transaction on behalf of yourself, you can use Web3.js to sign the message with your own private
否则,如果您代表自己发送已签名的交易,则可以使用 Web3.js 以您自己的私有身份对消息进行签名
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.