From 8059a719f33795e7c024fa84253f07df8073e783 Mon Sep 17 00:00:00 2001 From: "ray.wu" Date: Thu, 16 Dec 2021 18:09:25 +0800 Subject: [PATCH] fix usdt withdraw --- contracts/lib/SafeERC20.sol | 82 +++++++++++++++++++ .../root/TokenPredicates/ERC20Predicate.sol | 2 +- 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 contracts/lib/SafeERC20.sol diff --git a/contracts/lib/SafeERC20.sol b/contracts/lib/SafeERC20.sol new file mode 100644 index 0000000..2998b4d --- /dev/null +++ b/contracts/lib/SafeERC20.sol @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.6.0 <0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/math/SafeMath.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; + +/** + * @title SafeERC20 + * @dev Wrappers around ERC20 operations that throw on failure (when the token + * contract returns false). Tokens that return no value (and instead revert or + * throw on failure) are also supported, non-reverting calls are assumed to be + * successful. + * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, + * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. + */ +library SafeERC20 { + using SafeMath for uint256; + using Address for address; + + address constant USDTAddr = 0xa614f803B6FD780986A42c78Ec9c7f77e6DeD13C; + + function safeTransfer(IERC20 token, address to, uint256 value) internal { + if (address(token) == USDTAddr) { + (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0xa9059cbb, to, value)); + require(success, "SafeTRC20: low-level call failed"); + } else { + _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); + } + } + + function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { + _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); + } + + /** + * @dev Deprecated. This function has issues similar to the ones found in + * {IERC20-approve}, and its usage is discouraged. + * + * Whenever possible, use {safeIncreaseAllowance} and + * {safeDecreaseAllowance} instead. + */ + function safeApprove(IERC20 token, address spender, uint256 value) internal { + // safeApprove should only be called when setting an initial allowance, + // or when resetting it to zero. To increase and decrease it, use + // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' + // solhint-disable-next-line max-line-length + require((value == 0) || (token.allowance(address(this), spender) == 0), + "SafeERC20: approve from non-zero to non-zero allowance" + ); + _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); + } + + function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { + uint256 newAllowance = token.allowance(address(this), spender).add(value); + _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); + } + + function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { + uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); + _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); + } + + /** + * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement + * on the return value: the return value is optional (but if data is returned, it must not be false). + * @param token The token targeted by the call. + * @param data The call data (encoded using abi.encode or one of its variants). + */ + function _callOptionalReturn(IERC20 token, bytes memory data) private { + // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since + // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that + // the target address contains contract code and also asserts for success in the low-level call. + + bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); + if (returndata.length > 0) { // Return data is optional + // solhint-disable-next-line max-line-length + require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); + } + } +} diff --git a/contracts/root/TokenPredicates/ERC20Predicate.sol b/contracts/root/TokenPredicates/ERC20Predicate.sol index 64c86e8..a72f1ac 100755 --- a/contracts/root/TokenPredicates/ERC20Predicate.sol +++ b/contracts/root/TokenPredicates/ERC20Predicate.sol @@ -1,7 +1,7 @@ pragma solidity 0.6.6; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; +import {SafeERC20} from "../../lib/SafeERC20.sol"; import {AccessControlMixin} from "../../common/AccessControlMixin.sol"; import {RLPReader} from "../../lib/RLPReader.sol"; import {ITokenPredicate} from "./ITokenPredicate.sol";