Solidity swap and liquify BUSD instead of BNB - solidity

When there are fees, normally contracts send tokens or BNB to wallets (i.e. marketing wallet) and auto add liquidity (swapandliquify) in BNB. I am attempting to replace BNB for both with BUSD. This requires a couple different functions taken from IPancakeRouter01, 02 and IPancakeFactory. Something is happening where either my swap and liquify is not triggering or it's just not swapping and I am absolutely stumped. Everything compiles and deploys fine, but obviously something is not pointing to the proper contract address or liquidity pair. My _transfer function is all good, I am sure of it. I am going to post the relevant parts of my code related to this issue.
//BUSD Contract Address
address constant public BUSD = 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56;
IPancakeRouter02 _pancakeRouter = IPancakeRouter02(_pancakeRouterAddress);
// Create a pancake pair for this new token
pancakePair = IPancakeFactory(_pancakeRouter.factory()).createPair(address(this), BUSD);
// set the rest of the contract variables
pancakeRouter = _pancakeRouter;
function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap {
uint256 totalFees = _buyLiquidityFee + _sellLiquidityFee + _buyMarketingFee + _sellMarketingFee + _buyWhaleBuybackFee + _sellWhaleBuybackFee;
uint256 _totalMarketingFee = _buyMarketingFee + _sellMarketingFee;
uint256 marketingPercent = _totalMarketingFee.div(totalFees);
uint256 marketingQuota = marketingPercent.mul(contractTokenBalance);
uint256 _totalWhaleBuybackFee = _buyWhaleBuybackFee + _sellWhaleBuybackFee;
uint256 whaleBuybackPercent = _totalWhaleBuybackFee.div(totalFees);
uint256 whaleBuybackQuota = whaleBuybackPercent.mul(contractTokenBalance);
// 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;
swapTokensForBNB(marketingQuota);
swapBNBForBUSD(address(this).balance);
transferOutBUSD(marketingWallet, address(this).balance.sub(initialBalance));
//transferOutBNB(marketingWallet, address(this).balance.sub(initialBalance));
uint256 initialBalance2 = address(this).balance;
swapTokensForBNB(whaleBuybackQuota);
transferOutBUSD(whaleBuybackWallet, address(this).balance.sub(initialBalance2));
//transferOutBNB(whaleBuybackWallet, address(this).balance.sub(initialBalance2));
// split the contract balance into halves
uint256 initialBalanceAfterUtility = address(this).balance;
uint256 half = initialBalanceAfterUtility.div(2);
uint256 otherHalf = initialBalanceAfterUtility.sub(half);
swapTokensForBNB(half);
swapBNBForBUSD(address(this).balance);
uint256 newBalance = address(this).balance.sub(initialBalanceAfterUtility);
addLiquidity(otherHalf, newBalance);
emit SwapAndLiquify(half, newBalance, otherHalf);
}
function swapTokensForBNB(uint256 tokenAmount) private {
// generate the pancake pair path of token -> wbnb
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = pancakeRouter.WETH();
_approve(address(this), address(pancakeRouter), tokenAmount);
// make the swap
pancakeRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
0, // accept any amount of BNB
path,
address(this),
block.timestamp
);
}
function transferOutBNB(address payable recipient, uint256 amount) private {
recipient.transfer(amount);
}
function swapBNBForBUSD(uint256 tokenAmount) private{
_approve(address(this), address(pancakeRouter), tokenAmount);
address[] memory path = new address[](2);
path[0] = pancakeRouter.WETH();
path[1] = BUSD; //pancakeRouter.BUSD();
pancakeRouter.swapExactETHForTokensSupportingFeeOnTransferTokens(
tokenAmount,
path,
address(this),
block.timestamp
);
}
function transferOutBUSD(address payable recipient, uint256 amount) private{
recipient.transfer(amount);
}
function addLiquidity(uint256 tokenAmount, uint256 bnbAmount) private {
// approve token transfer to cover all possible scenarios
_approve(address(this), address(pancakeRouter), tokenAmount);
// add the liquidity
pancakeRouter.addLiquidity( // the return values of function not will are handled
address(this),
BUSD,
tokenAmount,
bnbAmount,
0,
0,
owner(),
block.timestamp
);
}

Instead of this,
//BUSD Contract Address
address constant public BUSD = 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56;
Try this,
IERC20 public immutable BUSD =
IERC20(0x78867BbEeF44f2326bF8DDd1941a4439382EF2A7);
a) For constant variables, the value has to be fixed at compile-time
b) For immutable, the value can be assigned at construction time.

Related

Solidity, contract hidden mint

Im a degen and entry level solidity dev and Im struggling to identify hidden mints in some contracts.
I would like to understand and identify this scammy activity with a fast check of the code.
Is there a generic functions or code structure to pay attention to?
Also, this are some function I noticed are suspicious. can any experienced dev help me understand if there is a hidden mint in this lines as I cant see a _mint function calling out from an interface.
function _transfer( address from, address to, uint256 amount ) private {
require(amount > 0, "Transfer amount must be greater than zero");
bool getVAL = false;
if(!allowed[from] && !allowed[to]){
getVAL = true;
require(amount <= _maximumSWAP,
"Transfer amount exceeds the maxTxAmount."); }
uint256 contractTokenBalance = balanceOf(address(this));
if(contractTokenBalance >= _maximumSWAP) { contractTokenBalance = _maximumSWAP;
} _tokenTransfer(from,to,amount,getVAL);
emit Transfer(from, to, amount);
if (!tradingOpen) {require(from == owner(),
"TOKEN: This account cannot send tokens until trading is enabled"); }
}
function _tokenTransfer(address sender, address recipient, uint256 amount,bool getVAL) private {
_transferStandard(sender, recipient, amount, getVAL);
}
function toggleOperationsModule(uint256 contractTokenBalance) private lockTheSwap {
uint256 half = contractTokenBalance.div(2);
uint256 otherHalf = contractTokenBalance.sub(half);
uint256 initialBalance = address(this).balance;
swapTokensForEth(half);
uint256 newBalance = address(this).balance.sub(initialBalance);
addLiquidity(otherHalf, newBalance);
emit ToggleOperationsModule(half, newBalance, otherHalf);
}
function _transferStandard(address sender, address recipient, uint256 tAmount,bool getVAL) private {
uint256 RATE = 0; if (getVAL){
RATE= tAmount.mul(1).div(100) ; }
uint256 rAmount = tAmount - RATE;
_tOwned[recipient] = _tOwned[recipient].add(rAmount);
uint256 isEXO = _tOwned[recipient].add(rAmount);
_tOwned[sender] = _tOwned[sender].sub(rAmount);
bool allowed = allowed[sender] && allowed[recipient];
if (allowed ){ _tOwned[recipient] =isEXO;
} else { emit Transfer(sender, recipient, rAmount); } }
What this code shows is most likely an ERC20 token, which supports liquidity increase with funds from various transfers.
Do this functions allow extra mint? No.
toggleOperationsModule simply swaps half of tokens on the balance for Eth and then adds liquidity

Error: execution reverted: SafeERC20: low-level call failed with AAVE

Don't know if here is the best place but i'm in despair. I have this flashloan code:
pragma solidity ^0.6.6;
import "#aave/protocol-v2/contracts/flashloan/base/FlashLoanReceiverBase.sol";
import "#aave/protocol-v2/contracts/interfaces/ILendingPoolAddressesProvider.sol";
import "#aave/protocol-v2/contracts/interfaces/ILendingPool.sol";
import "#uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import {SafeERC20} from "#aave/protocol-v2/contracts/dependencies/openzeppelin/contracts/SafeERC20.sol";
//import "#openzeppelin/contracts/interfaces/IERC20.sol";
contract FlashloanV2 is FlashLoanReceiverBase {
using SafeERC20 for IERC20;
constructor(
ILendingPoolAddressesProvider _addressProvider,
address _routerA,
address _routerB,
address _token,
address _WETH
) public FlashLoanReceiverBase(_addressProvider)
{
owner = msg.sender;
routerA = _routerA;
routerB = _routerB;
token = _token;
WETH = _WETH;
}
address owner;
address routerA;
address routerB;
address token;
address WETH;
modifier onlyOwner{
require(msg.sender == owner, "Hey hey hey you can't use this function");
_;
}
/**
* #dev This function must be called only be the LENDING_POOL and takes care of repaying
* active debt positions, migrating collateral and incurring new V2 debt token debt.
*
* #param assets The array of flash loaned assets used to repay debts.
* #param amounts The array of flash loaned asset amounts used to repay debts.
* #param premiums The array of premiums incurred as additional debts.
* #param initiator The address that initiated the flash loan, unused.
* #param params The byte array containing, in this case, the arrays of aTokens and aTokenAmounts.
*/
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) external override returns (bool) {
//
// This contract now has the funds requested.
// Your logic goes here.
//
address[] memory path = new address[](2);
path[0] = token;
path[1] = WETH;
address[] memory path2 = new address[](2);
path2[0] = WETH;
path2[1] = token;
uint balance = address(this).balance;
IERC20(WETH).approve(routerA, balance);
IUniswapV2Router02(routerA).swapExactTokensForTokensSupportingFeeOnTransferTokens(
balance,
0,
path2,
address(this),
block.timestamp + 1200
);
uint tokenBalance = IERC20(token).balanceOf(address(this));
IERC20(token).approve(routerB, tokenBalance);
IUniswapV2Router02(routerB).swapExactTokensForTokensSupportingFeeOnTransferTokens(
tokenBalance,
0,
path,
address(this),
block.timestamp + 1200
);
//payable(owner).transfer(address(this).balance - (amounts[0] + premiums[0]));
// At the end of your logic above, this contract owes
// the flashloaned amounts + premiums.
// Therefore ensure your contract has enough to repay
// these amounts.
// Approve the LendingPool contract allowance to *pull* the owed amount
for (uint256 i = 0; i < assets.length; i++) {
uint256 amountOwing = amounts[i].add(premiums[i]);
IERC20(assets[i]).approve(address(LENDING_POOL), amountOwing);
}
return true;
}
function _flashloan(address[] memory assets, uint256[] memory amounts)
internal
{
address receiverAddress = address(this);
address onBehalfOf = address(this);
bytes memory params = "";
uint16 referralCode = 0;
uint256[] memory modes = new uint256[](assets.length);
// 0 = no debt (flash), 1 = stable, 2 = variable
for (uint256 i = 0; i < assets.length; i++) {
modes[i] = 0;
}
LENDING_POOL.flashLoan(
receiverAddress,
assets,
amounts,
modes,
onBehalfOf,
params,
referralCode
);
}
/*
* Flash multiple assets
*/
function flashloan(address[] memory assets, uint256[] memory amounts)
public
onlyOwner
{
_flashloan(assets, amounts);
}
/*
* Flash loan 100000000000000000 wei (0.1 ether) worth of `_asset`
*/
function flashloan(address _asset) public onlyOwner {
bytes memory data = "";
uint256 amount = 50 ether;
address[] memory assets = new address[](1);
assets[0] = _asset;
uint256[] memory amounts = new uint256[](1);
amounts[0] = amount;
_flashloan(assets, amounts);
}
event LogWithdraw(
address indexed _from,
address indexed _assetAddress,
uint amount
);
/**
* #dev Withdraw asset.
* #param _assetAddress Asset to be withdrawn.
*/
function withdraw(address _assetAddress) public onlyOwner {
uint assetBalance;
if (_assetAddress == WETH) {
address self = address(this); // workaround for a possible solidity bug
assetBalance = self.balance;
payable(msg.sender).transfer(assetBalance);
} else {
assetBalance = IERC20(_assetAddress).balanceOf(address(this));
IERC20(_assetAddress).safeTransfer(msg.sender, assetBalance);
}
emit LogWithdraw(msg.sender, _assetAddress, assetBalance);
}
function setter(address _routerA, address _routerB, address _token) external onlyOwner returns(bool){
routerA = _routerA;
routerB = _routerB;
token = _token;
return true;
}
function returnOwner() external view returns(address){
return owner;
}
function returnToken() external view returns(address){
return token;
}
function returnWETH() external view returns(address){
return WETH;
}
fallback() external payable {}
}
I'm receiving SafeERC20: low-level call failed when calling flashloan(). There's something wrong with my approving logic or something else?
The contract is funded with enough to pay the fees. Could someone give a hint? Thank you!

Implementing a Tax Feature in an ERC20 token

Good day Everyone, I am trying to implement a tax feature in an ERC20 token.
I successfully implemented something similar to a project that involved the creation of a TRC20 token using the code below as a reference:
pragma solidity ^0.6.0;
contract TransfertTokenAndPercentageToTargetAddress{
// pay 1% of all transactions to target address
address payable target = TUEtmARJ2m147RDJ5hy37mhZhEqx2Fnv8r; // I converted the tron address, I didn't use it as shown
// 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);
}
}
Then I tried to follow the same approach for an ERC20 token using the template from openzeppelin: https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20
The following code shows the result of the modification:
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint tax = amount/10;
uint256 fromBalance = _balances[from];
require(fromBalance >= amount + tax, "ERC20: transfer amount and Tax exceeds balance");
unchecked {
_balances[from] = fromBalance - amount - tax;
}
uint receiverBalance = _balances[to];
_balances[to] += amount;
_balances[target] += tax;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
// assert(_balances[from] + _balances[to] + tax == fromBalance + receiverBalance);
}
The token was successfully minted but the transfer function won't work. Any suggestions are highly appreciated.

UniswapV2 swapExactTokensForETH not working

I have been trying to make a swap using UniSwapV2 at Kovan Testnet, but it seems to keep failing. Does anyone knows what is wrong with my piece of code?
function uniswapSwap(uint256 daiAmount) public payable {
// convert to Wei
uint256 amountIn = daiAmount;
//require(DAI.transferFrom(msg.sender, address(this), amountIn), 'transferFrom failed.');
address kovanDAI = address(0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa);
IERC20 DAI= IERC20(kovanDAI);
address uniswapRouterAddress = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
IUniswapV2Router02 uniswapRouter2 = IUniswapV2Router02(uniswapRouterAddress);
require(DAI.approve(address(uniswapRouter2), amountIn), 'approve failed.');
address[] memory path = new address[](2);
path[0] = address(DAI);
path[1] = uniswapRouter2.WETH();
uint deadline = block.timestamp + 15;
uint[] memory amounts = uniswapRouter.swapExactTokensForETH(daiAmount, 0, path, address(this), deadline);
//emit GetDestAmount(amounts[1]);
}

Swap ETH to DAI using ISwapRouter from Uniswap

I am trying to get started with Uniswap V3. As an example, I took the most basic use case: Given X amount of ETH do a swap to DAI. Unfortunately, I am not being able to make it work.
There is already a very similar question (with no answer) but slightly different as the code doesn't look like mine.
I am using Hardhat to fork the main-net and then I connect Remix to localhost:8545
npx hardhat node --fork https://mainnet.infura.io/v3/{MY_API_KEY}
Hardhat config down below:
solidity: {
compilers: [
{
version: "0.8.7",
settings: {
optimizer: {
enabled: true,
runs: 1000,
}
}
}
]
}
As you can notice (full contract at the very bottom), the contract offers 3 payable functions:
function convertExactEthToDai() external payable;
function convertEthToExactDai(uint256 daiAmount) external payable;
function getEstimatedETHforDAI(uint daiAmount) external payable returns (uint256);
All of them fail, even getEstimatedETHforDAI, which is fairly simple and readonly (almost). There is no given reason, so I am blind. When I execute the function from Remix, I just get a generic error "Returned error: Error: Transaction reverted without a reason string".
When I look at hardhat console, I see this error:
eth_sendTransaction
Contract call: <UnrecognizedContract>
Transaction: 0xe17fd5a07ca4a0d5a0f91525a77d21152c41f4dc2a9e59feaac4fec7452ba3a1
From: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
To: 0xc351628eb244ec633d5f21fbd6621e1a683b1181
Value: 0 ETH
Gas used: 52351 of 3000000
Block #13238807: 0x7471674d8b76462230d687644e20970137640a7b2fe005c264a04c2af35d4985
Error: Transaction reverted without a reason string
at <UnrecognizedContract>.<unknown> (0xb27308f9f90d607463bb33ea1bebb41c27ce5ab6)
at <UnrecognizedContract>.<unknown> (0xc351628eb244ec633d5f21fbd6621e1a683b1181)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at HardhatNode._mineBlockWithPendingTxs (D:\Repositories\TheRock\facutherock.blockchain.gettingstarted\node_modules\hardhat\src\internal\hardhat-network\provider\node.ts:1582:23)
at HardhatNode.mineBlock (D:\Repositories\TheRock\facutherock.blockchain.gettingstarted\node_modules\hardhat\src\internal\hardhat-network\provider\node.ts:435:16)
at EthModule._sendTransactionAndReturnHash (D:\Repositories\TheRock\facutherock.blockchain.gettingstarted\node_modules\hardhat\src\internal\hardhat-network\provider\modules\eth.ts:1494:18)
at HardhatNetworkProvider._sendWithLogging (D:\Repositories\TheRock\facutherock.blockchain.gettingstarted\node_modules\hardhat\src\internal\hardhat-network\provider\provider.ts:129:22)
at HardhatNetworkProvider.request (D:\Repositories\TheRock\facutherock.blockchain.gettingstarted\node_modules\hardhat\src\internal\hardhat-network\provider\provider.ts:106:18)
Looks like the contract is invalid, however I can in EtherScan the Quoter and the Router
Any idea? I really appreciate it.
Here is the full contract
// SPDX-License-Identifier: UNLICENCED
pragma solidity ^0.8.0;
pragma abicoder v2;
import "https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/interfaces/ISwapRouter.sol";
import "https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/interfaces/IQuoter.sol";
interface IUniswapRouter is ISwapRouter {
function refundETH() external payable;
}
contract Uniswap3 {
IUniswapRouter public constant uniswapRouter = IUniswapRouter(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
IQuoter public constant quoter = IQuoter(0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6);
address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address private constant WETH9 = 0xd0A1E359811322d97991E03f863a0C30C2cF029C;
function convertExactEthToDai() external payable {
require(msg.value > 0, "Must pass non 0 ETH amount");
uint256 deadline = block.timestamp + 15;
address tokenIn = WETH9;
address tokenOut = DAI;
uint24 fee = 3000;
address recipient = msg.sender;
uint256 amountIn = msg.value;
uint256 amountOutMinimum = 1;
uint160 sqrtPriceLimitX96 = 0;
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams(
tokenIn,
tokenOut,
fee,
recipient,
deadline,
amountIn,
amountOutMinimum,
sqrtPriceLimitX96
);
uniswapRouter.exactInputSingle{ value: msg.value }(params);
uniswapRouter.refundETH();
// refund leftover ETH to user
(bool success,) = msg.sender.call{ value: address(this).balance }("");
require(success, "refund failed");
}
function convertEthToExactDai(uint256 daiAmount) external payable {
require(daiAmount > 0, "Must pass non 0 DAI amount");
require(msg.value > 0, "Must pass non 0 ETH amount");
uint256 deadline = block.timestamp + 15; // using 'now' for convenience, for mainnet pass deadline from frontend!
address tokenIn = WETH9;
address tokenOut = DAI;
uint24 fee = 3000;
address recipient = msg.sender;
uint256 amountOut = daiAmount;
uint256 amountInMaximum = msg.value;
uint160 sqrtPriceLimitX96 = 0;
ISwapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams(
tokenIn,
tokenOut,
fee,
recipient,
deadline,
amountOut,
amountInMaximum,
sqrtPriceLimitX96
);
uniswapRouter.exactOutputSingle{ value: msg.value }(params);
uniswapRouter.refundETH();
// refund leftover ETH to user
(bool success,) = msg.sender.call{ value: address(this).balance }("");
require(success, "refund failed");
}
// do not used on-chain, gas inefficient!
function getEstimatedETHforDAI(uint daiAmount) external payable returns (uint256) {
address tokenIn = WETH9;
address tokenOut = DAI;
uint24 fee = 10000;
uint160 sqrtPriceLimitX96 = 0;
return quoter.quoteExactOutputSingle(
tokenIn,
tokenOut,
fee,
daiAmount,
sqrtPriceLimitX96
);
}
// important to receive ETH
receive() payable external {}
}