-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add asmERC20 implemetation to fix interaction with bad ERC20 after solc 0.4.22 #1344
Conversation
Also we think |
Copying our discussion from gitter: |
Hi @k06a! Thanks for this suggestion. The purpose of That said, I don't think the implementation of |
There's been some recent activity related to this: https://decentraland.org/blog/technology/safe-erc20-transfers I think we should extend our current So
This leaves out tokens that return Would love to hear anyone's thoughts on this. Particularly about that last paragraph. |
My two cents for this:
function transfer(address _to, uint256 _value) {
if (_to == 0x0) throw; // Prevent transfer to 0x0 address. Use burn() instead
if (_value <= 0) throw;
if (balanceOf[msg.sender] < _value) throw; // Check if the sender has enough
if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
balanceOf[msg.sender] = SafeMath.safeSub(balanceOf[msg.sender], _value); // Subtract from the sender
balanceOf[_to] = SafeMath.safeAdd(balanceOf[_to], _value); // Add the same to the recipient
Transfer(msg.sender, _to, _value); // Notify anyone listening that this transfer took place
}
E.g function safeTransfer(IERC20 _token, address _to, uint256 _value) internal returns (bool) {
uint256 prevBalance = _token.balanceOf(address(this));
if (prevBalance < _value) {
// Insufficient funds
return false;
}
address(_token).call(
abi.encodeWithSignature("transfer(address,uint256)", _to, _value)
);
if (prevBalance - _value != _token.balanceOf(address(this))) {
// Transfer failed
return false;
}
return true;
}
The full implementation of what we did at Decentraland is here |
How do you propose we handle such a situation? The only reasonable (for some definition of 'reasonable') way that I can think of is having some sort of registry of non-compliant tokens, and not performing the call for those when the value is 0.
Which inconsistencies do you worry about? The pre and post check approach is very interesting though.
That'd make it inconsistent, since some of the tokens do revert on failure. I'd rather all errors be handled the same way, and not give the false illusion that a contract may react to a failed call. |
Throw handling will only works with gas limiting to some constant value (maybe 250k gas?) |
a) Check pre and post-conditions as the transfer example here.
I mean, the inconsistencies of:
Checking pre and post-conditions are expensive but efficient
This library will be an abstract layer above ERC20 standard methods. So, will be used for new contracts, right? in that case, we could have two ways of using it like: require(token.asmTransfer(from, to, value), "Transfer failed") or if (approve(owner, 0)) {
} else {
} Tokens as BNB doesn't accept |
Pre and post checks should also respect that some tokens can have fees, for example EURS and USDT. |
1 similar comment
Pre and post checks should also respect that some tokens can have fees, for example EURS and USDT. |
I've been discussing this with @frangio and @nachomazzara and my opinion pretty much aligns with @nventuro's.
I think this makes sense. I'd assume that using SafeERC20 should be enough when dealing with third-party ERC20s, and that's not true right now.
I really doubt such implementation exists IRL. Had solidity been generating that kind of code as an optimization, everything would be broken now that they always check the There's still the possibility of someone doing that in asm, but I wouldn't support that.
That's fine if you want to normalize the different implementations to make them as compliant with ERC20 as possible. But I think the purpose of SafeERC20 is different. |
Closing in favor of #1655. |
Fixes no issues in this repo
🚀 Description
Allows smart contracts to interact with bad ERC20 implementations, ie returning void from
transfer
,transferFrom
orapprove
. Instead of revert introduced methods returnsbool
.New methods:
asmTransfer
asmTransferFrom
asmApprove
Info:
npm run lint:fix
).I'll do tests/docs/linter after the discussion.