Last active
June 23, 2022 01:08
-
-
Save BrendanChou/88a2eeb80947ff00bcf58ffdafeaeb61 to your computer and use it in GitHub Desktop.
Brendan's implementation of ERC20SafeTransfer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Made as proof-of-concept fix for https://github.com/ethereum/solidity/issues/4116 | |
pragma solidity 0.4.24; | |
library TokenInteract { | |
function balanceOf( | |
address token, | |
address owner | |
) | |
internal | |
view | |
returns (uint256) | |
{ | |
return GeneralERC20(token).balanceOf(owner); | |
} | |
function allowance( | |
address token, | |
address owner, | |
address spender | |
) | |
internal | |
view | |
returns (uint256) | |
{ | |
return GeneralERC20(token).allowance(owner, spender); | |
} | |
function approve( | |
address token, | |
address spender, | |
uint256 amount | |
) | |
internal | |
{ | |
GeneralERC20(token).approve(spender, amount); | |
require( | |
checkSuccess(), | |
"TokenInteract#approve: Approval failed" | |
); | |
} | |
function transfer( | |
address token, | |
address to, | |
uint256 amount | |
) | |
internal | |
{ | |
GeneralERC20(token).transfer(to, amount); | |
require( | |
checkSuccess(), | |
"TokenInteract#transfer: Transfer failed" | |
); | |
} | |
function transferFrom( | |
address token, | |
address from, | |
address to, | |
uint256 amount | |
) | |
internal | |
{ | |
GeneralERC20(token).transferFrom(from, to, amount); | |
require( | |
checkSuccess(), | |
"TokenInteract#transferFrom: TransferFrom failed" | |
); | |
} | |
/** | |
* Checks the return value of the previous function. Returns true if the previous function | |
* function returned 32 non-zero bytes or returned zero bytes. | |
*/ | |
function checkSuccess( | |
) | |
private | |
pure | |
returns (bool) | |
{ | |
uint256 returnValue = 0; | |
/* solium-disable-next-line security/no-inline-assembly */ | |
assembly { | |
// check number of bytes returned from last function call | |
switch returndatasize | |
// no bytes returned: assume success | |
case 0x0 { | |
returnValue := 1 | |
} | |
// 32 bytes returned: check if non-zero | |
case 0x20 { | |
// copy 32 bytes into scratch space | |
returndatacopy(0x0, 0x0, 0x20) | |
// load those bytes into returnValue | |
returnValue := mload(0x0) | |
} | |
// not sure what was returned: dont mark as success | |
default { } | |
} | |
return returnValue != 0; | |
} | |
} | |
/** | |
* Interface for using ERC20 Tokens. We have to use a special interface to call ERC20 functions so | |
* that we dont automatically revert when calling non-compliant tokens that have no return value for | |
* transfer(), transferFrom(), or approve(). | |
*/ | |
interface GeneralERC20 { | |
function totalSupply( | |
) | |
external | |
view | |
returns (uint256); | |
function balanceOf( | |
address who | |
) | |
external | |
view | |
returns (uint256); | |
function allowance( | |
address owner, | |
address spender | |
) | |
external | |
view | |
returns (uint256); | |
function transfer( | |
address to, | |
uint256 value | |
) | |
external; | |
function transferFrom( | |
address from, | |
address to, | |
uint256 value | |
) | |
external; | |
function approve( | |
address spender, | |
uint256 value | |
) | |
external; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment