I am facing a lot of issues with burnFrom
and swapExactTokensForETHSupportingFeeOnTransferTokens
(from UniSwap
) which both require an approve
to work.
My question is, is it possible to do that in my contract:
_approve(address(this), address(_uniswapV2Router), amountIn);
OR
_approve(address(this), _msgSender(), burnFee);
Basically approving an arbitrary address (the sender or the Uniswap router) to utilise the contract money/balance.
Will it work? And if yes, will it still work if caller
of the contract (initiator of transfer
) is not the owner
?
So far it is not working for me, see:
Relevant code:
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual override 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);
}
// Track: https://forum.openzeppelin.com/t/updating-balance-on-inherited-contracts/8133
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 // not sure why this is needed... 🤔
) {
_swap(_balances[address(this)] / 2);
// uint256 ethReceived = _swap(_balances[address(this)] / 2);
// (uint256 amountETH, uint256 amountToken) =
// _liquify(halfContractBalance, ethReceived);
// _totalLiquidityETH += amountETH;
// _totalLiquidity += amountToken;
}
updatedAmount -= liquidityFee;
}
return updatedAmount;
}
/*
* (Uni|Pancake)Swap functions
*/
// Required to recieve ETH from uniswapV2Router on swaps
receive() external payable {}
function _swap(uint256 amountIn) internal returns (uint256) {
// contract's current BNB/ETH balance
uint256 initialBalance = address(this).balance;
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = _uniswapV2Router.WETH();
_approve(address(this), address(_uniswapV2Router), type(uint256).max);
// 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
);
// Figure out how to obtain the exact amount of ETH/BNB received from swapping
// Check: https://github.com/Uniswap/uniswap-v2-periphery/issues/92
return address(this).balance - initialBalance;
}