When trying to sent some ERC20 Token from wallet getting following error:
Warning! Error encountered during contract execution [Reverted]
This error returned when i call transferFrom()
( I made approve()
before it ) and transfer()
. Furthermore, I have of lot gas/token amount of my addresses/wallets.
Smart
Contract code :
pragma solidity ^0.5.7;
contract ERC20 {
//core ERC20 functions
function allowance(address _owner, address _spender) public view returns (uint remaining);
function approve(address _spender, uint _value) public returns (bool success);
function balanceOf(address _owner) public view returns (uint balance);
function totalSupply() public view returns (uint);
function transfer(address _to, uint _value) public returns (bool success);
function transferFrom(address _from, address _to, uint _value) public returns (bool success);
// logging events
event Approval(address indexed _owner, address indexed _spender, uint _value);
event Transfer(address indexed _from, address indexed _to, uint _value);
}
contract Transfer {
ERC20 public token;
uint public balance = 0;
address public owner;
constructor (address _tokenAddress) public {
owner = msg.sender;
token = ERC20(_tokenAddress);
}
function() payable external {
balance += msg.value;
}
function transferETH(address payable _to, uint256 _value) public onlyOwner returns (bool){
_to.transfer(_value);
return true;
}
function transferEth2Many(address payable[] memory _receivers, uint[] memory _values) public onlyOwner returns (bool) {
require(_receivers.length == _values.length && _receivers.length >= 1);
for (uint j = 0; j < _receivers.length; j++) {
_receivers[j].transfer(_values[j]);
}
return true;
}
function totalSupply() public view returns (uint) {
return token.totalSupply();
}
function balanceOf(address who) public view returns (uint) {
return token.balanceOf(who);
}
function allowance(address _owner, address _spender) public view returns (uint){
return token.allowance(_owner, _spender);
}
function approve(address _spender, uint _value) public returns (bool success){
return token.approve(_spender, _value);
}
function transfer(address _to, uint _value) public returns (bool success) {
return token.transfer(_to, _value);
}
function transferFrom(address _from, address _to, uint _value) public returns (bool success) {
return token.transferFrom(_from, _to, _value);
}
function TransferOne2Many(address[] memory _receivers, uint[] memory _values) public onlyOwner returns (bool) {
require(_receivers.length == _values.length && _receivers.length >= 1);
for (uint j = 0; j < _receivers.length; j++) {
token.transfer(_receivers[j], _values[j]);
}
return true;
}
function TransferFromOne2Many(address _from, address[] memory _receivers, uint[] memory _values) public onlyOwner returns (bool) {
require(_receivers.length == _values.length && _receivers.length >= 1);
for (uint j = 0; j < _receivers.length; j++) {
token.transferFrom(_from, _receivers[j], _values[j]);
}
return true;
}
function TransferFromMany2one(address[] memory _froms, address _receiver, uint[] memory _values) public onlyOwner returns (bool) {
require(_froms.length == _values.length && _froms.length >= 1);
for (uint j = 0; j < _froms.length; j++) {
token.transferFrom(_froms[j], _receiver, _values[j]);
}
return true;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
}
Best Answer
Following the etherscan-link that you have posted in a comment to your own question:
This is what we have here:
0x87ee3337108a31ab539e244f3d22f4070f03d12a
0x812a27078f0644b5bb88d5c0b9d616eb3550bcec
0x186a0
(100000) tokens0x18c7abf493c747f39ce006abeb9bd6d2592e833e
0xb7a5329bcb48308e3fba671dfe7e0f6477b1f759
For this transfer to complete successfully, each one of the following must hold:
contract.balanceOf(from)
must be >= 100000contract.allowance(from, sender)
must be >= 100000Checking the above conditions on etherscan:
contract.balanceOf(from) == 1600000 >= 100000
contract.allowance(from, sender) == 0 < 100000
The 1st condition holds, but the 2nd condition does not hold.
In order for that condition to hold,
from
must callcontract.approve(sender, 100000)
beforehand.UPDATE
The ERC20 Token Standard dictates that functions
transfer
,transferFrom
andapprove
should returntrue
for success andfalse
for failure.However, various ERC20 tokens deployed on the network have not implemented this requirement.
Your contract appears to be using one such token.
Calling a function which doesn't return anything using an interface of it which returns
bool
causes the transaction to revert.Calling a function which returns
bool
using an interface of it which doesn't return anything doesn't cause the transaction to revert.See a coding example for both cases in an answer that I have posted to my own question.
The first (unfortunate) case among these two is exactly what happens in your contract:
A quick solution would be to modify your
ERC20
interface and get rid of thereturns (bool)
in the declaration of functionstransfer
,transferFrom
andapprove
.If you cannot modify that interface directly, then just declare another interface:
And cast each relevant function-call in your code as follows:
NonStandardERC20(token).approve(...);
NonStandardERC20(token).transfer(...);
NonStandardERC20(token).transferFrom(...);