BEP20 Tokens are not being swapped for BNB and sent to charity wallet - solidity

I'm trying to create a bep20-token where a percentage of the transaction volume is converted into BNB, and subsequently sent to a designated charity wallet to store the BNB for future donations. Another feature of this token is that a another part of the transaction is also swapped for BNB and locked together with the token in the liquidity pool. This last feature is working, however, the wallet I set up as the charity wallet is not receiving BNB. I have already set up a liquidity pool with the test tokens and minor amount of BNB thats how I learned its not doing what it was designed for. This token is a fork of YUMMY and the complete contract can be viewed here: https://bscscan.com/address/0x05f2df7b3d612a23fe12162a6c996447dce728a5#code
function sendBNBToCharity(uint256 amount) private {
swapTokensForEth(amount);
_charityWalletAddress.transfer(address(this).balance);
}
function _setCharityWallet(address payable charityWalletAddress) external onlyOwner() {
_charityWalletAddress = charityWalletAddress;
}
function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap {
// split the contract balance into thirds
uint256 halfOfLiquify = contractTokenBalance.div(4);
uint256 otherHalfOfLiquify = contractTokenBalance.div(4);
uint256 portionForFees = contractTokenBalance.sub(halfOfLiquify).sub(otherHalfOfLiquify);
// capture the contract's current ETH balance.
// this is so that we can capture exactly the amount of ETH that the
// swap creates, and not make the liquidity event include any ETH that
// has been manually sent to the contract
uint256 initialBalance = address(this).balance;
// swap tokens for ETH
swapTokensForEth(halfOfLiquify); // <- this breaks the ETH -> HATE swap when swap+liquify is triggered
swapTokensForEth(portionForFees);
// how much ETH did we just swap into?
uint256 newBalance = address(this).balance.sub(initialBalance);
// add liquidity to uniswap
addLiquidity(otherHalfOfLiquify, newBalance);
sendBNBToCharity(portionForFees);
emit SwapAndLiquify(halfOfLiquify, newBalance, otherHalfOfLiquify);
}
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
);
}

Your swapTokensForEth function is swapping to WETH, not to ETH. Wrapped ETH is a coin that holds ETH and makes it act like an ERC20 token, so that it can be used on Uniswap and other place.
To get ETH out of your WETH, you'll need call WETH.withdraw(amount), which will convert your WETH back to ETH.

Related

Allowance is returned zero even after approval

I was unit testing my contract and within the tests i approved that the smart contract should be able to spend the tokens of the msg.sender (the owner) and then tried to transferFrom function to transfer the tokens from the msg.sender to the contract. However, the first obstacle i faced was that the allowance is returned as zero when i called the transferFrom function. Now i was able to relearn that the transferFrom function should be another transaction for it to be able to work and i console loged all the variables making sure that the allowance is being changed when calling the approve function. However when i recall the transferFrom the error persists and shows me Insufficient balance!
`
This is my deposit function where the transferFrom is called only if the approval was a success
/**
* #notice addEth is a user function where the user chooses the pool and sends eth to it, funding it
* #param depositAmount is the eth being sent from the user to the pool
* #param poolId_ is the address of the pool being chosen by the user
*/
function deposit(uint256 depositAmount, uint256 poolId_) public{
// Check if the pool is either closed or paused or exists
Pool storage p = checkIfPoolExistsOrClosed(poolId_);
// Make sure the eth being sent is not equal to zero
if (depositAmount <= 0) revert WrongAmount();
// Check if the pool is empty, if it is the price of token is 1
if(p.valueInPool == 0) {
tokensForUser = depositAmount;
}else {
// Get the amount of tokens to be minted to the user
tokensForUser = (depositAmount /
(p.valueInPool/
IProperSubsetERC20(p.poolTokenAddress).totalSupply()));
}
// check if the approval was a success
if(!contractIsApproved[msg.sender]) revert ApprovalFailed();
// Send the USDC tokens to the fund contract
bool transfer = IProperSubsetUSDC(usdcAddress).transferFrom(msg.sender, address(this), depositAmount);
// Send the USDC tokens to the fund contract
// (bool success,)=usdcAddress.delegatecall(abi.encodeWithSignature('transfer(address,uint256)', address(this), depositAmount));
// Call the ERC20 contract to mint tokens to user
IProperSubsetERC20(p.poolTokenAddress).mint(msg.sender, tokensForUser);
// Update the amount of liquidity in the pool
p.valueInPool = p.valueInPool + depositAmount;
// Emit event after adding eth to pool
emit Deposit(msg.sender, poolId_, depositAmount);
}
This is my approval function where i call the approve function to add an allowance
/**
* #notice function to approve contract to spend the user's USDC tokens
* #param amount of usdt willing to give the contract approval for spending
*/
function approveUser(uint256 amount) public returns(bool){
// Approve spending the msg.sender tokens
(bool success,) = usdcAddress.delegatecall(abi.encodeWithSignature('approve(address,uint256)', address(this), amount));
// If the approve function is succesfull we update the map to show that this address is approved
if(success){
contractIsApproved[msg.sender] = true;
}
// Return if the function is successfull
return success;
}
`
Now these are the tests where the approve and the transferFrom function are called
it("Try approving for user 1 the transfer of their tokens from the contract", async function() {
await deployFunds.connect(signers[1]).approveUser(1000);
})
it("Try depositing and the price of the pool tokens should be equal to one since it is new", async function() {
const tx = await deployFunds.connect(signers[1]).deposit(1000, 2);
const receipt = await tx.wait();
filter = receipt.events?.filter((x) => {return x.event == "Deposit"});
poolId = filter.length > 0 ? filter[0].args[1] : '0x000';
tokensForUser = filter.length > 0 ? filter[0].args[2]: "0";
mintedTokens = await deployERC20.balanceOf(user1);
expect(filter.length).above(0);
expect(poolId).to.equal(2);
expect(tokensForUser).to.equal(1000);
})
I tried console logging all the variables being changed in the approve function and everything was checking out but when i console log the allowance when calling the transferFrom is is printed as zero. I then tried to put the approve function and the transferFrom in each transaction alone and still the error persists as Insufficient allowance
(bool success,) = usdcAddress.delegatecall(abi.encodeWithSignature('approve(address,uint256)', address(this), amount));
Delegatecall stores the state changes (updates a storage slot) in your contract - not in the usdcAddress contract.
In order to get approval from the user, they need to send a separate transaction executing the approve() function directly on the usdcAddress contract - not through any other contract.

Solidity, swap on uniswapV3

I want to implement a swap on UniV3 but the follow error appears:
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
execution reverted
I have approved the Weth via etherscan goerli so I don't know why is sending me this error.Any advice??
Here is the code:
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
pragma abicoder v2;
import '#uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol';
import '#uniswap/v3-periphery/contracts/libraries/TransferHelper.sol';
contract SwapExamples {
// For the scope of these swap examples,
// we will detail the design considerations when using `exactInput`, `exactInputSingle`, `exactOutput`, and `exactOutputSingle`.
// It should be noted that for the sake of these examples we pass in the swap router as a constructor argument instead of inheriting it.
// More advanced example contracts will detail how to inherit the swap router safely.
// This example swaps DAI/WETH9 for single path swaps and DAI/USDC/WETH9 for multi path swaps.
ISwapRouter public immutable swapRouter;
// Router = 0xE592427A0AEce92De3Edee1F18E0157C05861564
address public constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address public constant WETH = 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6; //0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address public constant USDC = 0xEEa85fdf0b05D1E0107A61b4b4DB1f345854B952;//0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
// For this example, we will set the pool fee to 0.3%.
uint24 public constant poolFee = 3000;
uint256 public UsdOut;
constructor(ISwapRouter _swapRouter) {
swapRouter = _swapRouter;
}
/// #notice swapExactInputSingle swaps a fixed amount of DAI for a maximum possible amount of WETH9
/// using the DAI/WETH9 0.3% pool by calling `exactInputSingle` in the swap router.
/// #dev The calling address must approve this contract to spend at least `amountIn` worth of its DAI for this function to succeed.
/// #param amountIn The exact amount of DAI that will be swapped for WETH9.
/// #return amountOut The amount of WETH9 received.
function swapExactInputSingle(uint256 amountIn) external returns (uint256 amountOut) {
// msg.sender must approve this contract
// TransferHelper.safeApprove(WETH, address(this), amountIn);
// Transfer the specified amount of DAI to this contract.
TransferHelper.safeTransferFrom(WETH, msg.sender, address(this), amountIn); //Envia de la wallet a aquest contract, no necessito.
// Approve the router to spend DAI.
TransferHelper.safeApprove(WETH, address(swapRouter), amountIn);
// Naively set amountOutMinimum to 0. In production, use an oracle or other data source to choose a safer value for amountOutMinimum.
// We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.
ISwapRouter.ExactInputSingleParams memory params =
ISwapRouter.ExactInputSingleParams({
tokenIn: WETH,
tokenOut: USDC,
fee: poolFee,
recipient: msg.sender,
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
});
// The call to `exactInputSingle` executes the swap.
amountOut = swapRouter.exactInputSingle(params);
UsdOut = amountOut;
}
}

Can a solidity smart contract execute the approve function in an erc20 contract on behalf of the msg.sender

Setting up a bank contract to perform deposits and withdraws. I was wondering if its possible for the bank contract can execute the approve function in the erc20 contract on behalf of the msg.sender for the tokens they are wanting to deposit.
Below is my attempt for the bank contract to call the erc20 token contracts approve function. However wouldn't the msg.sender be the bank contract address instead of the original msg.sender (second line of the depositToken function.) This sounds silly but is there a way for the contract to send the request passing in the msg.senders address? If not is there an integrated way for the msg.sender to approve the bank contract address and the amount to enable the bank contract to call the transferFrom function and be provided the allowance.
//best guess on what that would look like inside the function depositTokens
msg.sender = customer;
customer.IER20(usdt).approve.address(this), uint _amount;
address public usdt;
mapping(address => uint) public bankBalance;
constructor() public {
usdt = 0x77c24f0Af71257C0ee26e0E0a108F940D1698d53;
}
usdt = 0x77c24f0Af71257C0ee26e0E0a108F940D1698d53;
function depositTokens(uint _amount) public {
IER20(usdt).approve.address(this), uint _amount;
// Trasnfer usdt tokens to contract
IERC20(usdt).transferFrom(msg.sender, address(this), _amount);
// Update the bank balance in map
bankBalance[msg.sender] = bankBalance[msg.sender] + _amount;
}
//approve function in erc20
function approve(address delegate, uint256 numTokens) public override returns (bool) {
allowed[msg.sender][delegate] = numTokens;
emit Approval(msg.sender, delegate, numTokens);
return true;
The answer is no, the approve function takes the msg.sender as the one that gives allowance. You can see the most used OpenZeppelin implementation here.
However I can see what you are trying to do and I want to add that there is a way to automatically ask an EOA (externally owned account) or a user with a wallet to approve some tokens to the contract before sending a transaction.
I don't know if a wallet does it automatically or you have to code it in the UI but I think that is what you are looking for.
And then after the user already approved your bank, you can remove your first line in the deposit function

How to correctly use a BUSD liquidity pool

We're working on a BEP20 token and given the current market, we'd like to use a BUSD LP.
The only problem is that the reflections and other functions aren't compatible.
Transactions go through successfully, but the reflections and other functions aren't executed / distributed.
Some places I think might help:
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
Might changing WETH to something else help?
Or maybe here:
IUniswapV2Router02 pancakeswapV2Router = IUniswapV2Router02(0x10ED43C718714eb63d5aA57B78B54704E256024E);
_pancakeswapV2LiquidityPair = IUniswapV2Factory(pancakeswapV2Router.factory())
.createPair(address(this), pancakeswapV2Router.WETH());
_pancakeswapV2Router = pancakeswapV2Router;
emit Transfer(address(0), _msgSender(), _tTotal);
}
function addLiquidity(uint256 tokenAmount, uint256 bnbAmount) private {
// Approve token transfer to cover all possible scenarios
_approve(address(this), address(_pancakeswapV2Router), tokenAmount);
// Adds the liquidity and gives the LP tokens to the owner of this contract
// The LP tokens need to be manually locked
_pancakeswapV2Router.addLiquidityETH{value: bnbAmount}(
address(this),
tokenAmount,
0, // Take any amount of tokens (ratio varies)
0, // Take any amount of BNB (ratio varies)
owner(),
block.timestamp.add(300)
);
}
Thank you in advance for any help!

Sending ether in solidity smart contract

I'm writing a smart contract in solidity, and I need to send ether from my coinbase (eth.coinbase) to my friend coinbase (address = 0x0123).
If I try to use an address.send(value) the function doesn't decrease my account and doesn't increase my friend coin base.
I only can send ether in geth with "eth.sendTransaction(VALUE, {from:eth.coinbase, to:address})"
so I want to know if its possible to call an eth method in contract or a different way to send ether in smart contract
function withdraw() returns (bool) {
address x = 0x0123;
uint amount = 100 ether;
if (x.send(amount))
return true;
else
return false;
}
address.send does not propagate exception that's why you don't see any issue. Make sure you have enough Eth in your contract.
Have a look on this documentation that will explain how to set up your smart contract: https://developer.ibm.com/clouddataservices/2016/05/19/block-chain-technology-smart-contracts-and-ethereum/
You can use following function. just change variable name with yours.
function Transfer(uint amount,address reciever){
// check sender balance is less than of amount which he wants to send.
if(balance[msg.sender] < amount){
return;
}
// decrease sender's balance.
balance[msg.sender] = balance[msg.sender] - amount;
// increase reciever's balance.
balance[reciever] = balance[reciever] + amount;
// event
// transaction(msg.sender,reciever,amount);
}