Created
October 22, 2021 19:06
-
-
Save hskang9/8b187a3163cb33e25882fadc9bc6389a to your computer and use it in GitHub Desktop.
frontier EVM cannot inherit library for interface
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
// SPDX-License-Identifier: Apache-2.0 | |
pragma solidity =0.6.12; | |
pragma experimental ABIEncoderV2; | |
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 approve(address spender, 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 | |
); | |
/// @notice EIP 2612 | |
function permit( | |
address owner, | |
address spender, | |
uint256 value, | |
uint256 deadline, | |
uint8 v, | |
bytes32 r, | |
bytes32 s | |
) external; | |
/** | |
* @dev Moves `amount` tokens from `sender` to `recipient` using the | |
* allowance mechanism. `amount` is then deducted from the caller's | |
* allowance. | |
* | |
* Returns a boolean value indicating whether the operation succeeded. | |
* | |
* Emits a {Transfer} event. | |
*/ | |
function transferFrom( | |
address sender, | |
address recipient, | |
uint256 amount | |
) external returns (bool); | |
/** | |
* @dev Moves `amount` tokens from the caller's account to `recipient`. | |
* | |
* Returns a boolean value indicating whether the operation succeeded. | |
* | |
* Emits a {Transfer} event. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (bool); | |
} | |
library BoringERC20 { | |
bytes4 private constant SIG_SYMBOL = 0x95d89b41; // symbol() | |
bytes4 private constant SIG_NAME = 0x06fdde03; // name() | |
bytes4 private constant SIG_DECIMALS = 0x313ce567; // decimals() | |
bytes4 private constant SIG_TRANSFER = 0xa9059cbb; // transfer(address,uint256) | |
bytes4 private constant SIG_TRANSFER_FROM = 0x23b872dd; // transferFrom(address,address,uint256) | |
function returnDataToString(bytes memory data) | |
internal | |
pure | |
returns (string memory) | |
{ | |
if (data.length >= 64) { | |
return abi.decode(data, (string)); | |
} else if (data.length == 32) { | |
uint8 i = 0; | |
while (i < 32 && data[i] != 0) { | |
i++; | |
} | |
bytes memory bytesArray = new bytes(i); | |
for (i = 0; i < 32 && data[i] != 0; i++) { | |
bytesArray[i] = data[i]; | |
} | |
return string(bytesArray); | |
} else { | |
return "???"; | |
} | |
} | |
/// @notice Provides a safe ERC20.symbol version which returns '???' as fallback string. | |
/// @param token The address of the ERC-20 token contract. | |
/// @return (string) Token symbol. | |
function safeSymbol(IERC20 token) internal view returns (string memory) { | |
(bool success, bytes memory data) = address(token).staticcall( | |
abi.encodeWithSelector(SIG_SYMBOL) | |
); | |
return success ? returnDataToString(data) : "???"; | |
} | |
/// @notice Provides a safe ERC20.name version which returns '???' as fallback string. | |
/// @param token The address of the ERC-20 token contract. | |
/// @return (string) Token name. | |
function safeName(IERC20 token) internal view returns (string memory) { | |
(bool success, bytes memory data) = address(token).staticcall( | |
abi.encodeWithSelector(SIG_NAME) | |
); | |
return success ? returnDataToString(data) : "???"; | |
} | |
/// @notice Provides a safe ERC20.decimals version which returns '18' as fallback value. | |
/// @param token The address of the ERC-20 token contract. | |
/// @return (uint8) Token decimals. | |
function safeDecimals(IERC20 token) internal view returns (uint8) { | |
(bool success, bytes memory data) = address(token).staticcall( | |
abi.encodeWithSelector(SIG_DECIMALS) | |
); | |
return success && data.length == 32 ? abi.decode(data, (uint8)) : 18; | |
} | |
/// @notice Provides a safe ERC20.transfer version for different ERC-20 implementations. | |
/// Reverts on a failed transfer. | |
/// @param token The address of the ERC-20 token. | |
/// @param to Transfer tokens to. | |
/// @param amount The token amount. | |
function safeTransfer( | |
IERC20 token, | |
address to, | |
uint256 amount | |
) internal { | |
//(bool success) = token.transfer(to, amount); | |
(bool success, bytes memory data) = address(token).call( | |
abi.encodeWithSelector(SIG_TRANSFER, to, amount) | |
); | |
//require(success, "IERC20: transfer failed"); | |
require( | |
success && (data.length == 0 || abi.decode(data, (bool))), | |
"BoringERC20: Transfer failed" | |
); | |
} | |
/// @notice Provides a safe ERC20.transferFrom version for different ERC-20 implementations. | |
/// Reverts on a failed transfer. | |
/// @param token The address of the ERC-20 token. | |
/// @param from Transfer tokens from. | |
/// @param to Transfer tokens to. | |
/// @param amount The token amount. | |
function safeTransferFrom( | |
IERC20 token, | |
address from, | |
address to, | |
uint256 amount | |
) internal { | |
//(bool success) = token.transfer(to, amount); | |
(bool success, bytes memory data) = address(token).call( | |
abi.encodeWithSelector(SIG_TRANSFER_FROM, from, to, amount) | |
); | |
//require(success, "IERC20: transfer failed"); | |
require( | |
success && (data.length == 0 || abi.decode(data, (bool))), | |
"BoringERC20: TransferFrom failed" | |
); | |
} | |
} | |
contract Test { | |
using BoringERC20 for IERC20; | |
/// @notice Address of the LP token for each MCV2 pool. | |
IERC20 public lpToken; | |
function addToken(IERC20 token) public { | |
lpToken = token; | |
} | |
function test(uint256 id, address to, uint256 amount) public { | |
lpToken.safeTransferFrom(msg.sender, address(this), amount); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment