.balance method returning non-zero, while mapping (address => uint256) returning non-zero - ethereum

I am trying to create a token on the BSC without reflections, with a simple flat fee for a dev wallet, and another fee for liquidity.
I am getting an error on every call to the following function:
function _transferStandard(address sender, address recipient, uint256 tAmount) private {
require(balanceOf(sender) > tAmount, "Insuficient balance for transaction.");
(uint256 tTransferAmount, uint256 fee) = _getValues(tAmount);
_tOwned[sender] = _tOwned[sender].sub(tAmount);
_tOwned[devWallet] = _tOwned[devWallet].add(fee);
_tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
emit Transfer(sender, recipient, tTransferAmount);
}
Subtraction is overflowing whenever tokens are removed from the senders wallet. Upon further analysis I discovered that the following function:
function balanceOf(address _owner) public view returns (uint256 balance){
return _owner.balance;
}
Will return a correct value of 1721391030000000000 for the owner balance (max supply is transfered to owner after deployment of the contract). However, the following function, which one would expect the same output from, is returning 0, as in the wallet has no balance.
function balanceOf_tOwned(address _owner) public view returns (uint256 balance){
return _tOwned[_owner];
}
_tOwned, on the other hand, is a simple mapping variable.
mapping (address => uint256) private _tOwned;
I am confused as to why balances appear as 0 when _tOwned is used.
Edit: I have now tested the dead wallet address 0x0000000000000000000000000000000000000000 for both functions. The results are diferent for both:
balanceOf returns: 10491075026009005720565 balanceOf_tOwned returns:
115792089237316195423570985008687907853269984665640000000000000000000000000000
I am again puzzled as to what this means, but possibly it is the mapping is actually returning the conversion to my token from BNB? I.e. its value of 380,000 USD in BNB (https://bscscan.com/address/0x0000000000000000000000000000000000000000).
Full contract code:
// SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.12;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return payable(msg.sender);
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
library Address {
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return _functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
return _functionCallWithValue(target, data, value, errorMessage);
}
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// The actual contract
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () {
address msgSender = _msgSender();
_owner = msgSender;
renounceOwnership();
}
function owner() public view returns (address payable) {
return payable(_owner);
}
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
}
contract COOLCONTRACT is Context, IERC20, Ownable {
using SafeMath for uint256;
using Address for address;
mapping (address => uint256) private _tOwned;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private constant MAX = ~uint256(0);
uint256 _tTotal = 10 * 10**8 * 10**18;
uint256 private _rTotal = (MAX - (MAX % _tTotal));
string private _name = 'igb';
string private _symbol = 'yiibg';
uint8 private _decimals = 9;
constructor () {
_tOwned[owner()] = _rTotal;
}
// 80% donated, 20% used to fund the project
address payable private devWallet = payable(0x40C31d8F17338841FA1c8Af2F619B21428B1f358);
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _tTotal;
}
function balanceOf(address _owner) public view returns (uint256 balance){
return _owner.balance;
}
function shiet(address _owner) public view returns (uint256 balance){
return _tOwned[_owner];
}
function transfer(address recipient, uint256 amount) public override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _approve(address owner, address spender, uint256 amount) private {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _transfer(address sender, address recipient, uint256 amount) private {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
require(amount > 0, "Transfer amount must be greater than zero");
_transferStandard(sender, recipient, amount);
}
function _transferStandard(address sender, address recipient, uint256 tAmount) private {
require(balanceOf(sender) > tAmount, "Insuficient balance for transaction.");
(uint256 tTransferAmount, uint256 fee) = _getValues(tAmount);
_tOwned[sender] = _tOwned[sender].sub(tAmount);
_tOwned[devWallet] = _tOwned[devWallet].add(fee);
_tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
emit Transfer(sender, recipient, tTransferAmount);
}
function _getValues(uint256 tAmount) private pure returns (uint256, uint256) {
uint256 fee = tAmount.div(100).mul(10);
uint256 totalTransac = tAmount.sub(fee);
return (totalTransac, fee);
}
}

Related

Gas estimation failed - "code": -32000, "message": "execution reverted"

I just copied a smart contract in Arbitum Goerli and tried to deploy it in Remix IDE.
https://arbiscan.io/token/0xdd8e557c8804d326c72074e987de02a23ae6ef84#code
But I received this error.
I tried adjusting the Gas limit and WEI. No luck.
This is the error 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 appreciate your help in advance.
pragma solidity ^0.8.7;
pragma experimental ABIEncoderV2;
import "#openzeppelin/contracts/token/ERC20/IERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/utils/math/SafeMath.sol";
import "#openzeppelin/contracts/utils/Address.sol";
import "#uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol";
import "#uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import "#uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
contract LamboArbInu is Context, IERC20, Ownable {
using SafeMath for uint256;
using Address for address;
address private constant DEAD = 0x000000000000000000000000000000000000dEaD;
string private _name;
string private _symbol;
uint8 private _decimals;
address public router;
address public basePair;
uint256 public prevDevFee;
mapping(address => uint256) private _tOwned;
mapping(address => mapping(address => uint256)) private _allowances;
mapping(address => bool) private _isExcludedFromDevFee;
mapping(address => bool) private _isExcludedFromMaxAmount;
mapping(address => bool) private _isDevWallet;
address[] private _excluded;
address public _devWalletAddress;
uint256 private _tTotal;
uint256 public _devFee;
uint256 private _previousDevFee = _devFee;
uint256 public _maxTxAmount;
uint256 public _maxHeldAmount;
IUniswapV2Router02 public uniswapV2Router;
IUniswapV2Pair public uniswapV2Pair;
constructor(
address tokenOwner,
address devWalletAddress_,
address _router,
address _basePair
) {
_name = "LamboArbInu";
_symbol = "LAMBOARBINU";
_decimals = 18;
_tTotal = 1000000000 * 10**_decimals;
_tOwned[tokenOwner] = _tTotal;
_devFee = 4;
_previousDevFee = _devFee;
_devWalletAddress = devWalletAddress_;
_maxHeldAmount = _tTotal.mul(20).div(1000); // 2%
_maxTxAmount = _maxHeldAmount;
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(_router);
// Create a uniswap pair for this new token
uniswapV2Pair = IUniswapV2Pair(
IUniswapV2Factory(_uniswapV2Router.factory()).createPair(
address(this),
_basePair
)
);
// set the rest of the contract variables
uniswapV2Router = _uniswapV2Router;
//exclude owner and this contract from fee
_isExcludedFromDevFee[owner()] = true;
_isExcludedFromDevFee[address(this)] = true;
_isExcludedFromDevFee[_devWalletAddress] = true;
_isExcludedFromMaxAmount[owner()] = true;
_isExcludedFromMaxAmount[address(this)] = true;
_isExcludedFromMaxAmount[_devWalletAddress] = true;
//set wallet provided to true
_isDevWallet[_devWalletAddress] = true;
emit Transfer(address(0), tokenOwner, _tTotal);
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _tTotal;
}
function balanceOf(address account) public view override returns (uint256) {
return _tOwned[account];
}
function getBasePairAddr() public view returns (address) {
return basePair;
}
function transfer(address recipient, uint256 amount)
public
override
returns (bool)
{
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address _owner, address spender)
public
view
override
returns (uint256)
{
return _allowances[_owner][spender];
}
function approve(address spender, uint256 amount)
public
override
returns (bool)
{
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public override returns (bool) {
_transfer(sender, recipient, amount);
_approve(
sender,
_msgSender(),
_allowances[sender][_msgSender()].sub(
amount,
"ERC20: transfer amount exceeds allowance"
)
);
return true;
}
function increaseAllowance(address spender, uint256 addedValue)
public
virtual
returns (bool)
{
_approve(
_msgSender(),
spender,
_allowances[_msgSender()][spender].add(addedValue)
);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue)
public
virtual
returns (bool)
{
_approve(
_msgSender(),
spender,
_allowances[_msgSender()][spender].sub(
subtractedValue,
"ERC20: decreased allowance below zero"
)
);
return true;
}
function excludeFromFee(address account) public onlyOwner {
require(!_isExcludedFromDevFee[account], "Account is already excluded");
_isExcludedFromDevFee[account] = true;
}
function includeInFee(address account) public onlyOwner {
require(_isExcludedFromDevFee[account], "Account is already included");
_isExcludedFromDevFee[account] = false;
}
function excludeFromMaxAmount(address account) public onlyOwner {
require(
!_isExcludedFromMaxAmount[account],
"Account is already excluded"
);
_isExcludedFromMaxAmount[account] = true;
}
function includeInMaxAmount(address account) public onlyOwner {
require(
_isExcludedFromMaxAmount[account],
"Account is already included"
);
_isExcludedFromMaxAmount[account] = false;
}
function setDevFeePercent(uint256 devFee) external onlyOwner {
require(devFee >= 0, "teamFee out of range");
_devFee = devFee;
}
function setMaxTxPercent(uint256 maxTxPercent) external onlyOwner {
require(maxTxPercent <= 100, "maxTxPercent out of range");
_maxTxAmount = _tTotal.mul(maxTxPercent).div(10**2);
}
function setDevWalletAddress(address _addr) public onlyOwner {
require(!_isDevWallet[_addr], "Wallet address already set");
if (!_isExcludedFromDevFee[_addr]) {
excludeFromFee(_addr);
}
_isDevWallet[_addr] = true;
_devWalletAddress = _addr;
}
function replaceDevWalletAddress(address _addr, address _newAddr)
external
onlyOwner
{
require(_isDevWallet[_addr], "Wallet address not set previously");
if (_isExcludedFromDevFee[_addr]) {
includeInFee(_addr);
}
_isDevWallet[_addr] = false;
if (_devWalletAddress == _addr) {
setDevWalletAddress(_newAddr);
}
}
//to recieve ETH from uniswapV2Router when swaping
receive() external payable {}
function _getValues(uint256 tAmount)
private
view
returns (uint256, uint256)
{
uint256 tDev = calculateDevFee(tAmount);
uint256 tTransferAmount = tAmount.sub(tDev);
return (tTransferAmount, tDev);
}
function _takeDev(uint256 tDev) private {
_tOwned[_devWalletAddress] = _tOwned[_devWalletAddress].add(tDev);
}
function calculateDevFee(uint256 _amount) private view returns (uint256) {
return _amount.mul(_devFee).div(10**2);
}
function removeAllFee() private {
if (_devFee == 0) return;
_previousDevFee = _devFee;
_devFee = 0;
}
function restoreAllFee() private {
_devFee = _previousDevFee;
}
function isExcludedFromFee(address account) public view returns (bool) {
return _isExcludedFromDevFee[account];
}
function isExcludedFromMaxAmount(address account)
public
view
returns (bool)
{
return _isExcludedFromMaxAmount[account];
}
function _approve(
address _owner,
address spender,
uint256 amount
) private {
require(_owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[_owner][spender] = amount;
emit Approval(_owner, spender, amount);
}
function _transfer(
address from,
address to,
uint256 amount
) private {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
require(amount > 0, "Transfer amount must be greater than zero");
// Only limit max TX for swaps, not for standard transactions
if (
from == address(uniswapV2Router) || to == address(uniswapV2Router)
) {
if (
!_isExcludedFromMaxAmount[from] && !_isExcludedFromMaxAmount[to]
)
require(
amount <= _maxTxAmount,
"Transfer amount exceeds the maxTxAmount."
);
}
//indicates if fee should be deducted from transfer
bool takeFee = true;
//if any account belongs to _isExcludedFromDevFee account then remove the fee
if (_isExcludedFromDevFee[from] || _isExcludedFromDevFee[to]) {
takeFee = false;
}
if (!_isExcludedFromMaxAmount[to]) {
require(
_tOwned[to].add(amount) <= _maxHeldAmount,
"Recipient already owns maximum amount of tokens."
);
}
//transfer amount, it will take dev, liquidity fee
_tokenTransfer(from, to, amount, takeFee);
//reset tax fees
restoreAllFee();
}
function swapTokensForEth(uint256 tokenAmount) private {
// generate the uniswap pair path of token -> WHT
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = getBasePairAddr();
_approve(address(this), address(uniswapV2Router), tokenAmount);
// make the swap
uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
0, // accept any amount of ETH
path,
address(this),
block.timestamp
);
}
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
DEAD,
block.timestamp
);
}
//this method is responsible for taking all fee, if takeFee is true
function _tokenTransfer(
address sender,
address recipient,
uint256 amount,
bool takeFee
) private {
if (!takeFee) removeAllFee();
(uint256 tTransferAmount, uint256 tDev) = _getValues(amount);
_tOwned[sender] = _tOwned[sender].sub(amount);
_tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
_takeDev(tDev);
emit Transfer(sender, recipient, tTransferAmount);
}
function disableFees() public onlyOwner {
removeAllFee();
}
function enableFees() public onlyOwner {
restoreAllFee();
}
}

Minimal ERC20 contract for testing

I was searching for minimal ERC20 token implementation. The OpenZeppelin's ERC20 contract with all of these extension layers is too big for students tutoring
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
I wrote a TestERC20 smart-contract which implement IERC20 interface without inheritance.
It was used to test erc20-payment-gateway. I think that might be useful to the community too
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.7;
library Math {
function safeAdd(uint256 x, uint256 y) internal pure returns (uint256) {
uint256 z = x + y;
require(z >= x, "math-add-overflow");
return z;
}
function safeSub(uint256 x, uint256 y) internal pure returns (uint256) {
uint256 z = x - y;
require(z <= x, "math-sub-underflow");
return z;
}
}
contract TestERC20 {
uint256 public constant decimals = 18;
string public name;
string public symbol;
uint256 public totalSupply;
mapping (address => uint256) public balances;
mapping (address => mapping (address => uint256)) private allowances;
event Approval(address indexed src, address indexed usr, uint256 wad);
event Transfer(address indexed src, address indexed dst, uint256 wad);
function getChainId() public view returns(uint256) {
uint256 chainId;
assembly {
chainId := chainid()
}
return chainId;
}
constructor(string memory _symbol, string memory _name) {
symbol = _symbol;
name = _name;
}
function transfer(address dst, uint256 wad) external returns (bool) {
return transferFrom(msg.sender, dst, wad);
}
function transferFrom(address src, address dst, uint256 wad) public returns (bool) {
require(balances[src] >= wad, "nsufficient-balance");
if (src != msg.sender && allowances[src][msg.sender] != type(uint256).max) {
require(allowances[src][msg.sender] >= wad, "insufficient-allowances");
allowances[src][msg.sender] = Math.safeSub(allowances[src][msg.sender], wad);
}
balances[src] = Math.safeSub(balances[src], wad);
balances[dst] = Math.safeAdd(balances[dst], wad);
emit Transfer(src, dst, wad);
return true;
}
function mint(address usr, uint256 wad) public {
balances[usr] = Math.safeAdd(balances[usr], wad);
totalSupply = Math.safeAdd(totalSupply, wad);
emit Transfer(address(0), usr, wad);
}
function burn(address usr, uint256 wad) public {
require(balances[usr] >= wad, "insufficient-balance");
if (usr != msg.sender && allowances[usr][msg.sender] != type(uint256).max) {
require(allowances[usr][msg.sender] >= wad, "insufficient-allowances");
allowances[usr][msg.sender] = Math.safeSub(allowances[usr][msg.sender], wad);
}
balances[usr] = Math.safeSub(balances[usr], wad);
totalSupply = Math.safeSub(totalSupply, wad);
emit Transfer(usr, address(0), wad);
}
function approve(address usr, uint256 wad) external returns (bool) {
allowances[msg.sender][usr] = wad;
emit Approval(msg.sender, usr, wad);
return true;
}
function allowance(address owner, address spender) public view returns (uint256) {
return allowances[owner][spender];
}
function balanceOf(address account) public view returns (uint256) {
return balances[account];
}
}

Solidity Error : gas required exceeds allowance (25000000)

Im struggling with some solidity error that makes no sense to me, when calling the distribute function of this contract :
contract RewardsContract is Context, IERC20, Ownable {
using SafeMath for uint256;
using Address for address;
mapping (address => uint256) private _rOwned;
mapping (address => uint256) private _tOwned;
mapping (address => mapping (address => uint256)) private _allowances;
mapping (address => bool) private _isExcludedFromFee;
mapping (address => bool) private _isExcluded;
address[] private _excluded;
uint256 private constant MAX = ~uint256(0);
uint256 private _tTotal = 30000 * 10**18;
uint256 private _rTotal = (MAX - (MAX % _tTotal));
uint256 private _tFeeTotal;
string private _name = "RewardsContract";
string private _symbol = "RewardsContract";
uint8 private _decimals = 18;
uint256 public _taxFee = 2;
uint256 private _previousTaxFee = _taxFee;
uint256 public _liquidityFee = 18; //(2% liquidityAddition + 1% rewardsDistribution + 1% devExpenses)
uint256 private _previousLiquidityFee = _liquidityFee;
address [] public tokenHolder;
uint256 public numberOfTokenHolders = 0;
mapping(address => bool) public exist;
uint256 public ethFees;
//No limit
uint256 public _maxTxAmount = _tTotal;
address payable wallet;
IPancakeRouter02 public immutable pancakeRouter;
address public immutable pancakePair;
bool inSwapAndLiquify;
bool public swapAndLiquifyEnabled = false;
uint256 private minTokensBeforeSwap = 8;
event MinTokensBeforeSwapUpdated(uint256 minTokensBeforeSwap);
event SwapAndLiquifyEnabledUpdated(bool enabled);
event SwapAndLiquify(
uint256 tokensSwapped,
uint256 ethReceived,
uint256 tokensIntoLiqudity
);
modifier lockTheSwap {
inSwapAndLiquify = true;
_;
inSwapAndLiquify = false;
}
constructor () public {
_rOwned[_msgSender()] = _rTotal;
wallet = msg.sender;
IPancakeRouter02 _pancakeRouter = IPancakeRouter02(0xD99D1c33F9fC3444f8101754aBC46c52416550D1);
// Create a pancake pair for this new token
pancakePair = IPancakeFactory(_pancakeRouter.factory())
.createPair(address(this), _pancakeRouter.WETH());
// set the rest of the contract variables
pancakeRouter = _pancakeRouter;
//exclude owner and this contract from fee
_isExcludedFromFee[owner()] = true;
_isExcludedFromFee[address(this)] = true;
emit Transfer(address(0), _msgSender(), _tTotal);
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _tTotal;
}
function balanceOf(address account) public view override returns (uint256) {
if (_isExcluded[account]) return _tOwned[account];
return tokenFromReflection(_rOwned[account]);
}
function transfer(address recipient, uint256 amount) public override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function isExcludedFromReward(address account) public view returns (bool) {
return _isExcluded[account];
}
function totalFees() public view returns (uint256) {
return _tFeeTotal;
}
function deliver(uint256 tAmount) public {
address sender = _msgSender();
require(!_isExcluded[sender], "Excluded addresses cannot call this function");
(uint256 rAmount,,,,,) = _getValues(tAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_rTotal = _rTotal.sub(rAmount);
_tFeeTotal = _tFeeTotal.add(tAmount);
}
function reflectionFromToken(uint256 tAmount, bool deductTransferFee) public view returns(uint256) {
require(tAmount <= _tTotal, "Amount must be less than supply");
if (!deductTransferFee) {
(uint256 rAmount,,,,,) = _getValues(tAmount);
return rAmount;
} else {
(,uint256 rTransferAmount,,,,) = _getValues(tAmount);
return rTransferAmount;
}
}
function tokenFromReflection(uint256 rAmount) public view returns(uint256) {
require(rAmount <= _rTotal, "Amount must be less than total reflections");
uint256 currentRate = _getRate();
return rAmount.div(currentRate);
}
function excludeFromReward(address account) public onlyOwner() {
// require(account != 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, 'We can not exclude pancake router.');
require(!_isExcluded[account], "Account is already excluded");
if(_rOwned[account] > 0) {
_tOwned[account] = tokenFromReflection(_rOwned[account]);
}
_isExcluded[account] = true;
_excluded.push(account);
}
function includeInReward(address account) external onlyOwner() {
require(_isExcluded[account], "Account is already excluded");
for (uint256 i = 0; i < _excluded.length; i++) {
if (_excluded[i] == account) {
_excluded[i] = _excluded[_excluded.length - 1];
_tOwned[account] = 0;
_isExcluded[account] = false;
_excluded.pop();
break;
}
}
}
function _approve(address owner, address spender, uint256 amount) private {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
bool public limit = true;
function changeLimit() public onlyOwner(){
require(limit == true, 'limit is already false');
limit = false;
}
function _transfer(
address from,
address to,
uint256 amount
) private {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
require(amount > 0, "Transfer amount must be greater than zero");
if(limit == true && from != owner() && to != owner()){
if(to != pancakePair){
require(((balanceOf(to).add(amount)) <= 500 ether));
}
require(amount <= 100 ether, 'Transfer amount must be less than 100 tokens');
}
if(from != owner() && to != owner())
require(amount <= _maxTxAmount, "Transfer amount exceeds the maxTxAmount.");
// is the token balance of this contract address over the min number of
// tokens that we need to initiate a swap + liquidity lock?
// also, don't get caught in a circular liquidity event.
// also, don't swap & liquify if sender is pancake pair.
if(!exist[to]){
tokenHolder.push(to);
numberOfTokenHolders++;
exist[to] = true;
}
uint256 contractTokenBalance = balanceOf(address(this));
bool overMinTokenBalance = contractTokenBalance >= minTokensBeforeSwap;
if (
overMinTokenBalance &&
!inSwapAndLiquify &&
from != pancakePair &&
swapAndLiquifyEnabled
) {
//add liquidity
swapAndLiquify(contractTokenBalance);
}
//indicates if fee should be deducted from transfer
bool takeFee = true;
//if any account belongs to _isExcludedFromFee account then remove the fee
if(_isExcludedFromFee[from] || _isExcludedFromFee[to]){
takeFee = false;
}
//transfer amount, it will take tax, burn, liquidity fee
_tokenTransfer(from,to,amount,takeFee);
}
mapping(address => uint256) public myRewards;
function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap {
// split the contract balance into halves
uint256 forLiquidity = contractTokenBalance.div(2);
uint256 devExp = contractTokenBalance.div(4);
uint256 forRewards = contractTokenBalance.div(4);
// split the liquidity
uint256 half = forLiquidity.div(2);
uint256 otherHalf = forLiquidity.sub(half);
// 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(half.add(devExp).add(forRewards)); // <- this breaks the ETH -> HATE swap when swap+liquify is triggered
// how much ETH did we just swap into?
uint256 Balance = address(this).balance.sub(initialBalance);
uint256 oneThird = Balance.div(3);
ethFees = ethFees.add(oneThird);
wallet.transfer(oneThird);
// for(uint256 i = 0; i < numberOfTokenHolders; i++){
// uint256 share = (balanceOf(tokenHolder[i]).mul(ethFees)).div(totalSupply());
// myRewards[tokenHolder[i]] = myRewards[tokenHolder[i]].add(share);
//}
// add liquidity to pancake
addLiquidity(otherHalf, oneThird);
emit SwapAndLiquify(half, oneThird, otherHalf);
}
function seeRewards() public view returns(uint256){
address sender = msg.sender;
return myRewards[sender];
}
function getRewards() public returns(bool){
require(myRewards[msg.sender] > 0, 'You have zero rewards right now');
uint256 _rewards = myRewards[msg.sender];
myRewards[msg.sender] = myRewards[msg.sender].sub(_rewards);
msg.sender.transfer(_rewards);
return true;
}
function distribute() public returns(bool){
for(uint256 i = 0; i < numberOfTokenHolders; i++){
if(tokenHolder[i] != pancakePair && !_isExcluded[tokenHolder[i]]){
uint256 share = (balanceOf(tokenHolder[i]).mul(ethFees)).div(totalSupply()-(balanceOf(pancakePair)));
myRewards[tokenHolder[i]] = myRewards[tokenHolder[i]].add(share);
}
}
ethFees = 0;
}
function expectedRewards(address sender) public view returns(uint256){
uint256 _share = (balanceOf(sender).mul(ethFees)).div(totalSupply()-(balanceOf(pancakePair)));
return _share;
}
function swapTokensForEth(uint256 tokenAmount) private {
// generate the pancake pair path of token -> weth
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 ETH
path,
address(this),
block.timestamp
);
}
function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
// approve token transfer to cover all possible scenarios
_approve(address(this), address(pancakeRouter), tokenAmount);
// add the liquidity
pancakeRouter.addLiquidityETH{value: ethAmount}(
address(this),
tokenAmount,
0, // slippage is unavoidable
0, // slippage is unavoidable
owner(),
block.timestamp
);
}
//this method is responsible for taking all fee, if takeFee is true
function _tokenTransfer(address sender, address recipient, uint256 amount,bool takeFee) private {
if(!takeFee)
removeAllFee();
if (_isExcluded[sender] && !_isExcluded[recipient]) {
_transferFromExcluded(sender, recipient, amount);
} else if (!_isExcluded[sender] && _isExcluded[recipient]) {
_transferToExcluded(sender, recipient, amount);
} else if (!_isExcluded[sender] && !_isExcluded[recipient]) {
_transferStandard(sender, recipient, amount);
} else if (_isExcluded[sender] && _isExcluded[recipient]) {
_transferBothExcluded(sender, recipient, amount);
} else {
_transferStandard(sender, recipient, amount);
}
if(!takeFee)
restoreAllFee();
}
function _transferStandard(address sender, address recipient, uint256 tAmount) private {
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
_takeLiquidity(tLiquidity);
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
}
function _transferToExcluded(address sender, address recipient, uint256 tAmount) private {
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
_rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
_takeLiquidity(tLiquidity);
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
}
function _transferFromExcluded(address sender, address recipient, uint256 tAmount) private {
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
_tOwned[sender] = _tOwned[sender].sub(tAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
_takeLiquidity(tLiquidity);
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
}
function _transferBothExcluded(address sender, address recipient, uint256 tAmount) private {
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
_tOwned[sender] = _tOwned[sender].sub(tAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
_rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
_takeLiquidity(tLiquidity);
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
}
function _reflectFee(uint256 rFee, uint256 tFee) private {
_rTotal = _rTotal.sub(rFee);
_tFeeTotal = _tFeeTotal.add(tFee);
}
function _getValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256, uint256, uint256) {
(uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getTValues(tAmount);
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee) = _getRValues(tAmount, tFee, tLiquidity, _getRate());
return (rAmount, rTransferAmount, rFee, tTransferAmount, tFee, tLiquidity);
}
function _getTValues(uint256 tAmount) private view returns (uint256, uint256, uint256) {
uint256 tFee = calculateTaxFee(tAmount);
uint256 tLiquidity = calculateLiquidityFee(tAmount);
uint256 tTransferAmount = tAmount.sub(tFee).sub(tLiquidity);
return (tTransferAmount, tFee, tLiquidity);
}
function _getRValues(uint256 tAmount, uint256 tFee, uint256 tLiquidity, uint256 currentRate) private pure returns (uint256, uint256, uint256) {
uint256 rAmount = tAmount.mul(currentRate);
uint256 rFee = tFee.mul(currentRate);
uint256 rLiquidity = tLiquidity.mul(currentRate);
uint256 rTransferAmount = rAmount.sub(rFee).sub(rLiquidity);
return (rAmount, rTransferAmount, rFee);
}
function _getRate() private view returns(uint256) {
(uint256 rSupply, uint256 tSupply) = _getCurrentSupply();
return rSupply.div(tSupply);
}
function _getCurrentSupply() private view returns(uint256, uint256) {
uint256 rSupply = _rTotal;
uint256 tSupply = _tTotal;
for (uint256 i = 0; i < _excluded.length; i++) {
if (_rOwned[_excluded[i]] > rSupply || _tOwned[_excluded[i]] > tSupply) return (_rTotal, _tTotal);
rSupply = rSupply.sub(_rOwned[_excluded[i]]);
tSupply = tSupply.sub(_tOwned[_excluded[i]]);
}
if (rSupply < _rTotal.div(_tTotal)) return (_rTotal, _tTotal);
return (rSupply, tSupply);
}
function _takeLiquidity(uint256 tLiquidity) private {
uint256 currentRate = _getRate();
uint256 rLiquidity = tLiquidity.mul(currentRate);
_rOwned[address(this)] = _rOwned[address(this)].add(rLiquidity);
if(_isExcluded[address(this)])
_tOwned[address(this)] = _tOwned[address(this)].add(tLiquidity);
}
function calculateTaxFee(uint256 _amount) private view returns (uint256) {
return _amount.mul(_taxFee).div(
10**2
);
}
function calculateLiquidityFee(uint256 _amount) private view returns (uint256) {
return _amount.mul(_liquidityFee).div(
10**2
);
}
function removeAllFee() private {
if(_taxFee == 0 && _liquidityFee == 0) return;
_previousTaxFee = _taxFee;
_previousLiquidityFee = _liquidityFee;
_taxFee = 0;
_liquidityFee = 0;
}
function restoreAllFee() private {
_taxFee = _previousTaxFee;
_liquidityFee = _previousLiquidityFee;
}
function isExcludedFromFee(address account) public view returns(bool) {
return _isExcludedFromFee[account];
}
function excludeFromFee(address account) public onlyOwner {
_isExcludedFromFee[account] = true;
}
function includeInFee(address account) public onlyOwner {
_isExcludedFromFee[account] = false;
}
function setTaxFeePercent(uint256 taxFee) external onlyOwner() {
require(taxFee <= 10, "Maximum tax limit is 10 percent");
_taxFee = taxFee;
}
function setLiquidityFeePercent(uint256 liquidityFee) external onlyOwner() {
require(liquidityFee <= 10, "Maximum fee limit is 10 percent");
_liquidityFee = liquidityFee;
}
function setMaxTxPercent(uint256 maxTxPercent) external onlyOwner() {
_maxTxAmount = _tTotal.mul(maxTxPercent).div(
10**2
);
}
function setSwapAndLiquifyEnabled(bool _enabled) public onlyOwner {
swapAndLiquifyEnabled = _enabled;
emit SwapAndLiquifyEnabledUpdated(_enabled);
}
//to recieve ETH from pancakeRouter when swaping
receive() external payable {}
}
Knowing that ethFees is at the moment equal to 157053209615704422268
I'd like to understand why the EVM is throwing that error at execution.
Also theres something weird happening when calling expectedRewards(), it throws an out of gas exception (on a call ???)

How can I transfer ERC20 token by another smart contract?

I have designed an erc20 token and a smart contract to transfer that token, but when I trigger the function to transfer, the remix told me the following graph.
What I did was to deploy the token smart contract and then the DAO smart contract, then call the creatSubDAO function to start the transfer.
The relative code is below:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contract Dtoken:
contract Dtoken is IERC20{
string public name = "DAO Token";
string public symbol = "D";
uint256 public totalSupply = 1000000000000000000000000;
uint8 public decimals = 18;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
constructor() {
balanceOf[msg.sender] = totalSupply;
}
function transfer(address _to, uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value);
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
function approve(address _spender, uint256 _value) public returns (bool success) {
allowance[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(_value <= balanceOf[_from]);
require(_value <= allowance[_from][msg.sender]);
balanceOf[_from] -= _value;
balanceOf[_to] += _value;
allowance[_from][msg.sender] -= _value;
emit Transfer(_from, _to, _value);
return true;
}
}
contract MasterDao:
import "./Dtoken.sol";
contract MasterDAO {
uint proposalNum;
mapping (address => Member) public members;
mapping (uint => Proposal) public proposals;
mapping (uint => SubDAO) public subDAOs;
// SubDAO[] public subDAOs;
function createSubDAO (uint _poolGap, uint _DAOID, uint _rate, Dtoken _token) public returns (address daoAddress) {
SubDAO subDAO = new SubDAO(_poolGap, _DAOID, msg.sender, _rate, this, _token);
daoAddress = address(subDAO);
}}
SubDao Contract:
contract SubDAO {
uint proposalNum;
address lender;
uint poolGap;
uint currentStake;
uint256 public DAOID;
MasterDAO master;
address stakeItem;
uint rate;
Dtoken public token;
mapping(address => Member) members;
mapping (uint => Proposal) public proposals;
string[] description;
event Transfrom(address, uint);
struct Member {
address memberAddress;
string nickName;
bool alreadyExist;
}
struct Proposal {
string description;
address payable recipient;
bool executed;
uint proposalID;
address[] agreeMembers;
address[] disagreeMembers;
bool exectuable;
uint amount;
Dtoken token;
}
modifier membership (MasterDAO masterDAO, address _staker){
require(masterDAO.addressExist(_staker) == true);
_;
}
modifier lenderLimit {
require(msg.sender == lender);
_;
}
modifier balanceLimit(uint amount) {
require(amount <= poolGap - currentStake);
_;
}
constructor (uint _poolGap, uint _DAOID, address _lender, uint _rate, MasterDAO caller, Dtoken _token) {
currentStake = 0;
poolGap = _poolGap;
DAOID = _DAOID;
lender = _lender;
master = caller;
rate = _rate;
token = _token;
token.transferFrom(address(this), address(this), 10);
}
Did I do anything wrong to transfer the token? Thanks!
From the SubDao constructor:
token.transferFrom(address(this), address(this), 10);
This snippet is trying to transfer tokens from the just created SubDao address (1st argument) to the very same address (2nd argument).
The newly created SubDao address most likely doesn't own any tokens to transfer from in the first place.
If you want to transfer tokens from the MasterDao to the newly created SubDao, you can remove the transferFrom() from the SubDao constructor, and implement the transfer in the MasterDao function createSubDAO():
function createSubDAO (uint _poolGap, uint _DAOID, uint _rate, Dtoken _token) public returns (address daoAddress) {
SubDAO subDAO = new SubDAO(_poolGap, _DAOID, msg.sender, _rate, this, _token);
daoAddress = address(subDAO);
// transfer 10 units of the `Dtoken`
// from the `MasterDao` address
// to the newly created `SubDao` address
// assuming that `MasterDao` has sufficient token balance
Dtoken(_token).transfer(daoAddress, 10);
}}

Problem with sending ERC20 tokens from one smart contract to another one

I have an ERC20 token (Cryptos) and want to send some tokens to VulnerableTokenSale smart contract, but it shows zero balance for the token balance (get_balanceToken function). Is it possible to do that? I am using Remix on Ethereum website.
contract VulnerableTokenSale {
address public wallet;
uint256 rate;
ERC20 public token;
address public owner;
mapping(address => uint256) public balances;
address [] beneficiaries;
modifier onlyOwner() {
require(msg.sender == owner, "not owner");
_;
}
constructor(address _wallet, uint256 _rate, ERC20 _token)
public {
wallet = _wallet;
rate = _rate;
token = _token;
owner = msg.sender;
}
function sendTokensWithRatio(uint256 _numerator, uint256 _denominator) external onlyOwner {
require(_numerator <= _denominator);
for(uint256 i = 0; i < beneficiaries.length; i++){
address beneficiary = beneficiaries[i];
uint256 balance = balances[beneficiary];
if(balance > 0) {
uint256 amount = balance * _numerator;
amount = amount / _denominator;
balances[beneficiary] = balance - amount;
token.transfer(beneficiary, amount);
}
}
}
function purchaseTokens() public payable{
uint256 weiAmount = msg.value;
uint256 _tokenAmount = weiAmount * rate;
beneficiaries.push(msg.sender);
balances[msg.sender] = balances[msg.sender] + _tokenAmount;
}
}
Think your constructor is slightly wrong, I have never seen anyone take in an ERC token directly.
I have something like this in my contracts:
constructor(address _wallet, uint256 _rate, address _tokenAddress) public {
wallet = _wallet;
rate = _rate;
token = ERC20(_tokenAddress);
owner = msg.sender;
}
Note you need the ERC20 interface for the above to work:
interface ERC20 {
function totalSupply() public view returns (uint);
function balanceOf(address tokenOwner) public view returns (uint balance);
function allowance(address tokenOwner, address spender) public view returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);
// optional
function name() external view returns (string);
function symbol() external view returns (string);
function decimals() external view returns (string);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}