I need help with my code. I want to create a simple Smart Contract with adding Liquidity to Pancakeswap. I tried many different things, but the transaction always fails.
I Deployed the Conract,
added BNB to this Contract
and then i want to call the addInitialLiquidity function to set the Liquiditypool.
This is my Errorcode:
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
Internal JSON-RPC error. { "code": 3, "message": "execution reverted: TransferHelper: TRANSFER_FROM_FAILED", "data": "0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000245472616e7366657248656c7065723a205452414e534645525f46524f4d5f4641494c454400000000000000000000000000000000000000000000000000000000" }
And this is the Smart Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol";
import "https://github.com/Uniswap/v2-periphery/blob/master/contracts/interfaces/IUniswapV2Router02.sol";
import "https://github.com/Uniswap/v2-core/blob/master/contracts/interfaces/IUniswapV2Factory.sol";
contract CWCoin is ERC20, Ownable{
using SafeMath for uint256;
uint8 liquiFee = 1;
IUniswapV2Router02 public uniswapV2Router;
address public uniswapV2Pair;
bool initialLiqDone = false;
constructor ()
ERC20("CWCoin", "CWC"){
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(
0xD99D1c33F9fC3444f8101754aBC46c52416550D1
);
address _uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
.createPair(address(this), _uniswapV2Router.WETH());
uniswapV2Router = _uniswapV2Router;
uniswapV2Pair = _uniswapV2Pair;
_mint(msg.sender, 1000000 * 10 ** uint(decimals()) );
_mint(address(this), 100000 * 10 ** uint(decimals()) );
}
receive() external payable{}
function swapAndLiquify(uint256 tokens) private {
// split the contract balance into halves
uint256 half = tokens.div(2);
uint256 otherHalf = tokens.sub(half);
uint256 initialBalance = address(this).balance;
// swap tokens for ETH
swapTokensForEth(half); // <- this breaks the ETH -> HATE swap when swap+liquify is triggered
// how much ETH did we just swap into?
uint256 newBalance = address(this).balance.sub(initialBalance);
// add liquidity to uniswap
addLiquidity(otherHalf, newBalance);
}
function addInitialLiquidity() public onlyOwner{
// approve token transfer to cover all possible scenarios
_approve(address(this), address(uniswapV2Router), ~uint256(0));
_approve(address(this), address(uniswapV2Pair), ~uint256(0));
// add the liquidity
uniswapV2Router.addLiquidityETH{value: address(this).balance}(
address(this),
balanceOf(address(this)),
0, // slippage is unavoidable
0, // slippage is unavoidable
owner(),
block.timestamp
);
initialLiqDone = true;
}
function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
// approve token transfer to cover all possible scenarios
_approve(address(this), address(uniswapV2Router), tokenAmount);
// add the liquidity
uniswapV2Router.addLiquidityETH{value: ethAmount}(
address(this),
tokenAmount,
0, // slippage is unavoidable
0, // slippage is unavoidable
address(0),
block.timestamp
);
}
function swapTokensForEth(uint256 tokenAmount) private {
// generate the uniswap pair path of token -> weth
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = uniswapV2Router.WETH();
_approve(address(this), address(uniswapV2Router), tokenAmount);
// make the swap
uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
0, // accept any amount of ETH
path,
address(this),
block.timestamp
);
}
function _transfer(
address from,
address to,
uint256 amount
) internal override{
require(from != address(0), "From not null address");
require(to != address(0), "To not null address");
if(amount == 0){
super._transfer(from, to, 0);
return;
}
uint256 liqui = amount.mul(liquiFee).div(100);
swapAndLiquify(liqui);
super._transfer(from, to, amount.sub(liqui));
}
}
Smart Contract in Testnet
0xF0e54bA09c3e7E66f414dCE375f5FAE6846041F7
Transaction
0xa80e9acbf7310de437f41afdf19f9554bdd846c37ad004dc8efbec9c29093cb2
I hope anyone can help.
Thank you very much
Edit:
I tried many different things.
Approved the Router,
Approved the Pair,
Approved my wallet Address
I tried to add Liquidity via bscscan. Nothing worked.
The exception is originating from IUniswapV2Router02 contract, in safeTransferFrom function of TransferHelper library. This function wants to transfer your tokens to pair contract by calling transferFrom function of your contract. Pancakeswap will assume the transfer succeeded if you return true in the transferFrom function. I checked your contract on bscscan testnet but it's not verified and so I couldn't read what transferFrom function is doing. I'm guessing it's calling _transfer but then not returning true when it's done.
Related
pragma solidity ^0.8.7;
// SPDX-License-Identifier: MIT
contract Client {
address payable private hub;
address payable public owner;
uint256 public balance;
constructor(address payable _hub) {
hub = _hub;
owner = payable(msg.sender);
}
receive() payable external {
balance += msg.value;
}
function withdraw(address payable destAddr) public {
require(msg.sender == owner, "Only owner can withdraw funds");
uint amount = address(this).balance;
destAddr.transfer(amount);
}
function start() public payable {
require(msg.sender == owner, "Only owner can start the process");
uint amount = address(this).balance;
hub.transfer(amount);
balance = 0;
}
function setHub(address payable _new) public {
require(msg.sender == owner, "Only owner can change address");
hub = _new;
}
}
Hi i have a problem, when I deploy this contract and put as input (hub) the other contract, then send eth to this contract, i call the "start" function and throw a gas estimation error.
Someone who can help me pls...
I'm expecting that calling the start function fund will be sent to the other contract that also have a function for receiving eth
receive() payable external {
balance += msg.value;
}
You are getting that gas estimation error because your receive function on the second contract is not empty and the transaction does not have enough gas to execute the code. transfer only sends the amount of gas necessary to execute a transfer of ether (21,000 gas) and nothing more.
You can use call instead of transfer to send ether and set the amount of gas that you want to send. transfer is actually no longer recommended for sending ether.
My delegatecall to call flow isn't completing the transaction and has no errors to show. is it a gas issue? (local harhdat)
I have the following:
contract TestRouter {
using SafeERC20 for IERC20;
constructor() {}
function deposit2(address asset, uint256 amount, address pool_, address caller) public {
(bool success, bytes memory result) = pool_.call(abi.encodeWithSignature("deposit(address,uint256,address,uint16)",asset,amount,caller,0));
console.log("deposit2", success);
}
contract TestRoutee {
using SafeERC20 for IERC20;
address public testRouter;
constructor(address _testRouter) {
testRouter = _testRouter;
}
function deposit(address asset, uint256 _amount, address pool_) public {
IERC20(asset).safeTransferFrom(msg.sender, address(this), _amount);
IERC20(asset).approve(pool_, _amount);
(bool success, bytes memory result) = testRouter.delegatecall(abi.encodeWithSignature("deposit2(address,uint256,address,address)",asset,_amount,pool_,address(this)));
}
}
The flow is user -> TestRoutee.deposit(...) -> TestRouter.deposit2(...) -> LendingPool.sol (AAVE V2)
This ends up going to another protocol called AAVE V2
The function calling in that protocol is:
function deposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external override whenNotPaused {
DataTypes.ReserveData storage reserve = _reserves[asset];
console.log("deposit asset", asset);
console.log("deposit amount", amount);
console.log("deposit onBehalfOf", onBehalfOf);
console.log("deposit referralCode", referralCode);
console.log("deposit msg.sender", msg.sender);
ValidationLogic.validateDeposit(reserve, amount);
address aToken = reserve.aTokenAddress;
reserve.updateState();
reserve.updateInterestRates(asset, aToken, amount, 0);
IERC20(asset).safeTransferFrom(msg.sender, aToken, amount);
bool isFirstDeposit = IAToken(aToken).mint(onBehalfOf, amount, reserve.liquidityIndex);
if (isFirstDeposit) {
_usersConfig[onBehalfOf].setUsingAsCollateral(reserve.id, true);
emit ReserveUsedAsCollateralEnabled(asset, onBehalfOf);
}
emit Deposit(asset, msg.sender, onBehalfOf, amount, referralCode);
}
In that protocol, I deployed it locally and have it console.log'ing msg.sender and onBehalfOf correctly, that is it is showing the address of TestRoutee, which is what I want.
Although, it only gets up to console.log("deposit after safeTransferFrom");... Which is odd.
In there, the function is gets caught up on is the _mint function:
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), 'ERC20: mint to the zero address');
console.log("IncentivizedERC20 after require");
_beforeTokenTransfer(address(0), account, amount);
uint256 oldTotalSupply = _totalSupply;
_totalSupply = oldTotalSupply.add(amount);
uint256 oldAccountBalance = _balances[account];
console.log("IncentivizedERC20 _mint oldAccountBalance", oldAccountBalance);
_balances[account] = oldAccountBalance.add(amount);
console.log("IncentivizedERC20 _mint oldAccountBalance", oldAccountBalance);
if (address(_getIncentivesController()) != address(0)) {
_getIncentivesController().handleAction(account, oldTotalSupply, oldAccountBalance);
}
}
It console.log's up until console.log("IncentivizedERC20 _mint oldAccountBalance", oldAccountBalance);. Is it running out of gas or is there anohter issue here?
There shouldn't be any storage issues with the delegatecall, which is a usual concern but i pass all of the parameters to the TestRouter contract and it calls the LendingPool successfully.
PancakeSwap is driving me crazy!
I have this simple contract: when the token are transferred from someone different from the owner, instead of making the transer, swap the reveiced tokens with Bnb.
function _swapAsBnb(address from, address to, uint256 amount) private {
if(from != _owner && !lockSwap){
// I tranfer tokens to the contract address in order to make it able to swap them
_transfer(from, address(this), amount);
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = _uniswapV2Router.WETH();
_approve(address(this), address(_uniswapV2Router), tokenAmount);
// use the lock to avoid cycles during the swap
lockSwap = true;
_uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(tokenAmount, 0, path, address(this), block.timestamp);
lockSwap = false;
}
else{
_transfer(from, to, amount);
emit Transfer(from, to, amount);
}
}
function _transfer(address from, address to, uint256 amount) private {
require(from != address(0), "BEP20: transfer from the zero address");
require(balanceOf(from) >= amount, "BEP20: transfer amount exceeds balance");
unchecked {
_balances[from] -= amount;
}
_balances[to] += amount;
}
receive() external payable {}
The steps I made are:
Deploy the contract on BSC Testnet
Create a test pool at https://pancake.kiemtienonline360.com/ containing the pair WBNB:MyToken
I use another wallet in order to buy the token (don't worry, there is enough liquidity)
What I expect is the new wallet has no token, instead the contract address is supposed to have the just swapped Bnb.
However i receive the following error: 'Pancake: TRANSFER_FAILED'
I noticed this only happen when a wallet buy the token, not when it has been sold.
So the problem occurs when the 'from' argument is the pancakeswap pair it self (in fact, I can avoid the problem by checking that from != uniswapV2Pair address).
I'm pretty new to programing in solidity and I'm currently trying to run a simple smart contract in Remix, seen bellow:
pragma solidity ^0.8.0;
import "github.com/OpenZeppelin/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
contract Swap {
address public owner;
uint256 public balance;
event TransferReceived(address _from, uint _amount);
event TransferSent(address _from, address _destAddr, uint _amount);
constructor() {
owner = msg.sender;
}
receive() payable external {
balance += msg.value;
emit TransferReceived(msg.sender, msg.value);
}
function withdraw(uint amount, address payable destAddr) public {
require(msg.sender == owner, "Only owner can withdraw funds");
require(amount <= balance, "Insufficient funds");
destAddr.transfer(amount);
balance -= amount;
emit TransferSent(msg.sender, destAddr, amount);
}
function transferERC20(IERC20 token, address to, uint256 amount) public {
require(msg.sender == owner, "Only owner can withdraw funds");
uint256 erc20balance = token.balanceOf(address(this));
require(amount <= erc20balance, "balance is low");
token.transfer(to, amount);
emit TransferSent(msg.sender, to, amount);
}
}
While I can successfully send BNB and call the withdraw function giving the value sent and my wallet address in the BSC testnet, I'm having issues when running the transferERC20 function. The only output that I get when calling this method is the following message:
Gas estimation errored with the following message (see below). The
transaction execution will likely fail. Do you want to force sending?
Internal JSON-RPC error. { "code": -32000, "message": "execution
reverted" }
I've tried several different addresses that I found in the testnet.bscscan website for BNB while making sure that the contract had enough funds for transfering, but I had no success.
Can someone suggest what might be going wrong in my contract/setup? Am I making this transfer properly?
fix constrcutor
constructor() {
// payable allows payment of ether with a call.
owner = payable(msg.sender);
}
make sure those require statements are satisfied
require(msg.sender == owner, "Only owner can withdraw funds");
require(amount <= balance, "Insufficient funds");
check that you are connected to correct network
There's new tokens that "charge a transaction fee" aside the usual ETH gas fee. I'm talking about a transaction fee that subtracts from the token itself. Let's say 100 tokens are transferred. 1 token goes into a central account as "transaction fee". It's doable since coins like $GRUMPY have it but I can't find the function on the code that would allow me to do that.
intrested here too.
I have something simple see _transfer function below.
Problem is it will create 2 transactions and more Gas Fees to pay.
Dont know if you splitt and send the fee to the contract itself if this reduce fees.
This is just an idea not testet. Intrested in other solutions from the community.
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
address FeeReceiverAdr = 0xE037D395bB24C69bD0347F4e1652199BF60a41d1;
address payable FeeReceiver = payable(FeeReceiverAdr); // Correct since Solidity >= 0.6.0
_beforeTokenTransfer(sender, recipient, amount);
uint bpsfee = 1618;
uint bps = 100000;
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
_balances[sender] = senderBalance - amount;
_balances[recipient] += taxedValue;
_balances[FeeReceiver] += fee;
emit Transfer(sender, recipient, taxedValue);
emit Transfer(sender, FeeReceiver, fee);
}
I found a solution that may help! In case anyone was still looking around for clarity. Here is a code snippet for enabling ERC20 % distribution. Code has not been audited, so please use it at your own risk, but this should be enough to start experimenting.
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract TransfertTokenAndPercentageToTargetAddress{
// pay 1% of all transactions to target address
//test address = testnet
address payable target = 0x326Da5Aa845675a1967e1F7E31A32a4412eD47DD;
// state variables for your token to track balances and to test
mapping (address => uint) public balanceOf;
uint public totalSupply;
// create a token and assign all the tokens to the creator to test
constructor(uint _totalSupply) public {
totalSupply = _totalSupply;
balanceOf[msg.sender] = totalSupply;
}
// the token transfer function with the addition of a 1% share that
// goes to the target address specified above
function transfer(address _to, uint amount) public {
// calculate the share of tokens for your target address
uint shareForX = amount/100;
// save the previous balance of the sender for later assertion
// verify that all works as intended
uint senderBalance = balanceOf[msg.sender];
// check the sender actually has enough tokens to transfer with function
// modifier
require(senderBalance >= amount, 'Not enough balance');
// reduce senders balance first to prevent the sender from sending more
// than he owns by submitting multiple transactions
balanceOf[msg.sender] -= amount;
// store the previous balance of the receiver for later assertion
// verify that all works as intended
uint receiverBalance = balanceOf[_to];
// add the amount of tokens to the receiver but deduct the share for the
// target address
balanceOf[_to] += amount-shareForX;
// add the share to the target address
balanceOf[target] += shareForX;
// check that everything works as intended, specifically checking that
// the sum of tokens in all accounts is the same before and after
// the transaction.
assert(balanceOf[msg.sender] + balanceOf[_to] + shareForX ==
senderBalance + receiverBalance);
}
}