Context I am trying to build a smart contract of a ERC20 token which comprehends the creation of the relative WETH/token pair on Uniswap V2.
Code The smart contract is as follow:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@uniswap/v2-core/contracts/interfaces/iUniswapV2Factory.sol";
import "@uniswap/v2-core/contracts/interfaces/iUniswapV2Pair.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IWETH.sol";
contract BarnaTokenInu is Ownable, ERC20 {
using Address for address;
string constant __name = "BARNATOKENINU";
string constant __symbol = "BTI";
uint256 constant __decimals = 18;
uint256 constant initialInvestment = 0.002 * 10**18;
uint256 constant fractionForOwner = 20;
uint256 constant deadlineForLiquidityProvision = 20 * 60;
uint256 constant initialSupply = 1e9 * 10**__decimals;
address public router_address;
IUniswapV2Router02 public router;
IUniswapV2Factory public factory;
IUniswapV2Pair public pair;
address public liquidityPoolPair;
IWETH public iweth; // weth object interface
IERC20 public weth;
constructor(address _router_address) ERC20(__name, __symbol) {
router_address = _router_address;
router = IUniswapV2Router02(router_address);
factory = IUniswapV2Factory(router.factory());
liquidityPoolPair = factory.createPair(router.WETH(), address(this));
pair = IUniswapV2Pair(liquidityPoolPair);
iweth = IWETH(router.WETH());
weth = IERC20(router.WETH());
_approve(owner(), router_address, type(uint256).max);
_approve(address(this), router_address, type(uint256).max);
_mint(owner(), initialSupply); // mint token
}
function getPoolReserves() public view returns (uint112, uint112) {
(uint112 reserveToken1, uint112 reserveToken2, ) = pair.getReserves();
return (reserveToken1, reserveToken2);
}
function swapETHforWETH() public payable {
iweth.deposit{value: msg.value}();
weth.transfer(msg.sender, msg.value);
}
function addInitialLiquidity() public payable onlyOwner {
weth.approve(router_address, initialInvestment);
weth.approve(owner(), initialInvestment);
router.addLiquidityETH{value: msg.value}(
address(this),
(initialSupply * fractionForOwner) / 100,
(initialSupply * fractionForOwner) / 100,
initialInvestment,
owner(),
block.timestamp + deadlineForLiquidityProvision
);
}
The brownie main script from which the smart contract is deployed is as follows:
def deploy_token_contract(_account):
if network.show_active() in LOCAL_DEVELOPMENT_ENVIRONMENTS:
router = get_account(index=9)
else:
router = config["networks"][network.show_active()]["router_address"]
return BarnaTokenInu.deploy(router, {"from": _account})
def main():
account = get_account()
contract = deploy_token_contract(account)
contract.swapETHforWETH({"from": account, "value": 0.02 * 10**18})
contract.addInitialLiquidity({"from": account, "value": 0.02 *
10**18})
Issue After the creation of the pair, I am not able to add liquidity to the pool, given that:
- I have enough ETH in my account
- I have made all the due approvals
I keep receiving the following error:
VirtualMachineError: revert: TransferHelper: TRANSFER_FROM_FAILED
Full error trace:
Transaction sent: 0x7ffd26ac40fe40b9eb211b94402b8ddcc60ebb311178755c457b393b34035f87
Gas price: 0.0 gwei Gas limit: 12000000 Nonce: 20
BarnaTokenInu.addInitialLiquidity confirmed (TransferHelper: TRANSFER_FROM_FAILED)
Block: 15919924 Gas used: 87214 (0.73%)
File "C:\Users\sma157555\AppData\Local\Programs\Python\Python310\lib\site-
packages\brownie\_cli\run.py", line 51, in main
return_value, frame = run(
File "C:\Users\sma157555\AppData\Local\Programs\Python\Python310\lib\site-
packages\brownie\project\scripts.py", line 110, in run
return_value = f_locals[method_name](*args, **kwargs)
File ".\scripts\main.py", line 30, in main
contract.addInitialLiquidity({"from": account})
File "C:\Users\sma157555\AppData\Local\Programs\Python\Python310\lib\site-
packages\brownie\network\contract.py", line 1861, in __call__
return self.transact(*args)
File "C:\Users\sma157555\AppData\Local\Programs\Python\Python310\lib\site-
packages\brownie\network\contract.py", line 1734, in transact
return tx["from"].transfer(
File "C:\Users\sma157555\AppData\Local\Programs\Python\Python310\lib\site-
packages\brownie\network\account.py", line 682, in transfer
receipt._raise_if_reverted(exc)
File "C:\Users\sma157555\AppData\Local\Programs\Python\Python310\lib\site-
packages\brownie\network\transaction.py", line 446, in _raise_if_reverted
raise exc._with_attr(
VirtualMachineError: revert: TransferHelper: TRANSFER_FROM_FAILED
Trace step -1, program counter 3601:
File "contracts/BarnaTokenInu.sol", lines 183-190, in BarnaTokenInu.addInitialLiquidity:
weth.approve(router_address, initialInvestment);
weth.approve(owner(), initialInvestment);
router.addLiquidityETH(
address(this),
(initialSupply * fractionForOwner) / 100,
(initialSupply * fractionForOwner) / 100,
initialInvestment,
owner(),
block.timestamp + deadlineForLiquidityProvision
);
}
Is anybody able to detect the flaw?
EDIT - SOLVED
I was unable to add liquidity because the add liquidity transaction sender is the contract from which the function is called...and there were no tokens on it...once I minted some tokens during contract deployment, everything worked