diff --git a/contracts/fees/OneSplitAdapter.sol b/contracts/fees/OneSplitAdapter.sol index 9d87c6ef..2b7363c0 100644 --- a/contracts/fees/OneSplitAdapter.sol +++ b/contracts/fees/OneSplitAdapter.sol @@ -38,9 +38,10 @@ contract OneSplitAdapter is IExchangeAdapter { /// @param _tokens the list of token addresses to approve function approveExchange(IERC20[] calldata _tokens) external override { for (uint256 i = 0; i < _tokens.length; i++) { - if (!_tokens[i].isETH()) { - _tokens[i].universalApprove(0x1814222fa8c8c1C1bf380e3BBFBd9De8657Da476, UintConstants.maxUintMinus1()); - } + _tokens[i].universalApprove( + 0x1814222fa8c8c1C1bf380e3BBFBd9De8657Da476, + UintConstants.maxUintMinus1() + ); } } diff --git a/contracts/flashloan/base/FlashLoanReceiverBase.sol b/contracts/flashloan/base/FlashLoanReceiverBase.sol index fb865030..95ce9229 100644 --- a/contracts/flashloan/base/FlashLoanReceiverBase.sol +++ b/contracts/flashloan/base/FlashLoanReceiverBase.sol @@ -21,17 +21,9 @@ abstract contract FlashLoanReceiverBase is IFlashLoanReceiver { receive() external payable {} function transferFundsBackToPoolInternal(address _reserve, uint256 _amount) internal { - - address payable core = addressesProvider.getLendingPoolCore(); - - transferInternal(core, _reserve, _amount); - } - - function transferInternal(address payable _destination, address _reserve, uint256 _amount) internal { - IERC20(_reserve).universalTransfer(_destination, _amount); - } - - function getBalanceInternal(address _target, address _reserve) internal view returns(uint256) { - return IERC20(_reserve).universalBalanceOf(_target); + IERC20(_reserve).universalTransfer( + addressesProvider.getLendingPoolCore(), // lending-pool core address + _amount + ); } } diff --git a/contracts/libraries/UniversalERC20.sol b/contracts/libraries/UniversalERC20.sol index 7feccd10..89283b9c 100644 --- a/contracts/libraries/UniversalERC20.sol +++ b/contracts/libraries/UniversalERC20.sol @@ -4,6 +4,12 @@ import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; +/** +* @title UniversalERC20 library +* @author Aave inspired by @k06a (Anton Bukov) +* @note original version: https://github.com/CryptoManiacsZone/1inchProtocol/blob/master/contracts/UniversalERC20.sol +* @dev Provides unified interface for ERC20 and native ETH operations +**/ library UniversalERC20 { using SafeMath for uint256; using SafeERC20 for IERC20; @@ -11,17 +17,24 @@ library UniversalERC20 { IERC20 private constant ZERO_ADDRESS = IERC20( 0x0000000000000000000000000000000000000000 ); + // @notice mock address of ETH IERC20 private constant ETH_ADDRESS = IERC20( 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE ); + /** + * @dev Moves amount of asset from caller to recipient + * @param token underlying asset address + * @param to asset recipient + * @param amount to move + **/ function universalTransfer( IERC20 token, address to, uint256 amount - ) internal returns (bool) { + ) internal { if (amount == 0) { - return true; + return; } if (isETH(token)) { @@ -30,9 +43,16 @@ library UniversalERC20 { } else { token.safeTransfer(to, amount); } - return true; } + /** + * @dev Moves amount of asset from sender to recipient + * @param token underlying asset address + * @param from asset sender + * @param to asset recipient + * @param amount to move + * @param returnExcess if true returns exceeded amount to sender + **/ function universalTransferFrom( IERC20 token, address from, @@ -67,6 +87,11 @@ library UniversalERC20 { } } + /** + * @dev Moves amount of asset from caller to this contract + * @param token underlying asset address + * @param amount to move + **/ function universalTransferFromSenderToThis(IERC20 token, uint256 amount) internal { @@ -88,6 +113,12 @@ library UniversalERC20 { } } + /** + * @dev Sets the allowance over the caller's tokens to recipient address. + * @param token underlying asset address + * @param to allowance recipient + * @param amount of the allowance + **/ function universalApprove( IERC20 token, address to, @@ -100,7 +131,12 @@ library UniversalERC20 { token.safeApprove(to, amount); } } - + /** + * @dev Returns the amount of underlying asset owned by address + * @param token underlying asset address + * @param who address to check + * @returns balance of the who address + **/ function universalBalanceOf(IERC20 token, address who) internal view @@ -113,6 +149,11 @@ library UniversalERC20 { } } + /** + * @dev Returns decimals of underlying asset + * @param token underlying asset address + * @returns decimals + **/ function universalDecimals(IERC20 token) internal view returns (uint256) { if (isETH(token)) { return 18; @@ -130,6 +171,11 @@ library UniversalERC20 { return (success && data.length > 0) ? abi.decode(data, (uint256)) : 18; } + /** + * @dev Checks is underlying asset ETH or not + * @param token underlying asset address + * @returns boolean + **/ function isETH(IERC20 token) internal pure returns (bool) { return (address(token) == address(ZERO_ADDRESS) || address(token) == address(ETH_ADDRESS)); diff --git a/contracts/mocks/flashloan/MockFlashLoanReceiver.sol b/contracts/mocks/flashloan/MockFlashLoanReceiver.sol index 6b80ea1a..203439d2 100644 --- a/contracts/mocks/flashloan/MockFlashLoanReceiver.sol +++ b/contracts/mocks/flashloan/MockFlashLoanReceiver.sol @@ -36,7 +36,10 @@ contract MockFlashLoanReceiver is FlashLoanReceiverBase { //check the contract has the specified balance - require(_amount <= getBalanceInternal(address(this), _reserve), "Invalid balance for the contract"); + require( + _amount <= IERC20(_reserve).universalBalanceOf(address(this)), + "Invalid balance for the contract" + ); if(failExecution) { emit ExecutedWithFail(_reserve, _amount, _fee);