v2-periphery
v2-periphery copied to clipboard
TransferHelper: TRANSFER_FROM_FAILED
react_devtools_backend.js:2557 Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"code":-32603,"message":"execution reverted: TransferHelper: TRANSFER_FROM_FAILED","data":{"originalError":{"code":3,"data":"0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000245472616e7366657248656c7065723a205452414e534645525f46524f4d5f4641494c454400000000000000000000000000000000000000000000000000000000","message":"execution reverted: TransferHelper: TRANSFER_FROM_FAILED"}}}, method="estimateGas", transaction={"from":"0x7F87bBc2Eb7911c8961c8506032d31d624894725","to":"0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D","value":{"type":"BigNumber","hex":"0x0de0b6b3a7640000"},"data":"0xf305d719000000000000000000000000c936c5a29f55006f2b1c84480bf2d77286e5944300000000000000000000000000000000000027716b6a0adc2d677c080000000000000000000000000000000000000000000027716b6a0adc2d677c08000000000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000007f87bbc2eb7911c8961c8506032d31d6248947250000000000000000000000000000000000000000000000000000000060a5149c","accessList":null}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.1.1)
at e.value (index.ts:205)
at e.value (index.ts:217)
at E (json-rpc-provider.ts:76)
at n.<anonymous> (json-rpc-provider.ts:508)
at c (runtime.js:63)
at Generator._invoke (runtime.js:293)
at Generator.throw (runtime.js:118)
at s (4.1d476024.chunk.js:2)
Help?
Thanks aress31, justin is working on this in https://github.com/Uniswap/uniswap-interface/issues/1582
@aress31 does the token take fee on transfer or anything special?
Also, can you give the address of that token on mainnet?
@justindomingue, yes it does indeed take a fee on transaction, to be more precise a liquidity fee
.
- Contract address:
0xA22E26fdD6c982f884fBF70C18FB9bc292025cA7
- Testnet:
Ropsten
- Relevant code:
function _transfer(
address sender,
address recipient,
uint256 amount
)
internal
virtual
notNull(amount)
{
require(
_balances[sender] >= amount,
"ERC20: transfer amount exceeds balance"
);
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
require(
sender != recipient,
"_transfer: 'sender' cannot also be 'recipient'"
);
if (!_isExcludedFromFees[sender] && !_isExcludedFromFees[recipient]) {
uint256 updatedAmount = _beforeTokenTransfer(sender, amount);
amount = updatedAmount;
}
_balances[sender] -= amount;
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
}
function _beforeTokenTransfer(address sender, uint256 amount)
internal
returns (uint256)
{
uint256 updatedAmount = amount;
if (_liquidityTax != 0) {
uint256 liquidityFee = (amount * _liquidityTax) / 100;
_balances[sender] -= liquidityFee;
_balances[address(this)] += liquidityFee;
emit Transfer(sender, address(this), liquidityFee);
if (
_balances[address(this)] >= _minTokensRequiredBeforeSwap &&
_isAutoSwapAndLiquify &&
sender != _uniswapV2Pair
) {
uint256 ethReceived = _swap(_balances[address(this)] / 2);
}
updatedAmount -= liquidityFee;
}
return updatedAmount;
}
receive() external payable {
emit Received(_msgSender(), msg.value);
}
function _swap(uint256 amountIn) internal returns (uint256) {
uint256 initialBalance = address(this).balance;
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = _uniswapV2Router.WETH();
// Change back to address(this)
_approve(address(this), address(_uniswapV2Router), amountIn);
// uint256 allowed = _allowances[address(this)][address(_uniswapV2Router)];
// emit Test(amountIn, path, allowed, (block.timestamp + 5 minutes)); <- amountIn is OK and allowance is OK
// The problem is here
// Swap tokens for ETH/BNB
_uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
amountIn,
0, // TODO: use an Oracle
path,
address(this), // this contract will receive the ETH that were swapped from the token
(block.timestamp + 5 minutes)
);
// Check: https://github.com/Uniswap/uniswap-v2-periphery/issues/92
return address(this).balance - initialBalance;
}
What slippage are you using? Is your token taking 50% before transfer? Maybe try setting to 80% slippage for debugging?
The liquidity fee is of 5% only that is definitely not a slippage issue, if I comment:
_uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
amountIn,
0, // TODO: use an Oracle
path,
address(this), // this contract will receive the ETH that were swapped from the token
(block.timestamp + 5 minutes)
);
Then everything works but obviously I want my contract to swap tokens. No one so far has been able to help me with this issue, I do not see anything wrong with this code, if you do PLEASE point out the bug.
Transferred to uniswap-v2-periphery which should have better context to help you @aress31.
Thanks @justindomingue also just realised I mixed up two different issues for the adding liquidity
bug, I can confirm that your latest fix resolved the issue!
This second issue remains however still open and happens when swapping a token on the front-end, my contract fails due to:
_uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
amountIn,
0, // TODO: use an Oracle
path,
address(this), // this contract will receive the ETH that were swapped from the token
(block.timestamp + 5 minutes)
);
Hello, what was the solution for your bug @aress31 please ? we are in the same situation… thank you for your answer
Hello, what was the solution for your bug @aress31 please ? we are in the same situation… thank you for your answer
Below is the solution to this famous error:
https://medium.com/@italo.honorato/how-to-resolve-transferhelper-error-transfer-from-failed-fb4c8bf6488c
Basically the error happens because it is not possible to approve a permission for the UNISWAP_V2_ROUTER to spend tokens from the ContractSwapOnUniswap address, why by default the ERC20 approve function will not recognize ContractSwapOnUniswap as msg.sender . That is, the TransferHelper: TRANSFER_FROM_FAILED error occurs because the UNISWAP_V2_ROUTER does not have the necessary permission in the token contract to spend balance of ContractSwapOnUniswap .
It concludes that this is a design error of the ERC20 standard itself applied to contracts that make exchanges from other accounts. If I'm wrong, please correct me.
Does anyone know how to guide me on how to open a discussion on the subject, for possible improvements in this?
Pretty sure this error is caused by the swap and liquify feature that you seem to be using. Had same exact issue, and I know how to handle token approval which the dude above is mentioning, for eg. in newer Openzeppelin ERC20 standard you can approve infinite amount by approving "type(uint).max" amount in the constructor of the code, and allowance never gets reduced. Tried running swap and liquify separately and it worked, tried swapping with S&L turned off and swaps worked, same thing with regular token transfers, they worked with S&L. However Uni doesn't seem to support swaps and S&L in the same call