Liquidus Finance
Search
⌃K

KyberSwapLIQ.sol

Contract used to make swaps using the KyberSwap API.

Smart Contract Code

// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;
​
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
​
interface ILiquidusFeeEstimation {
function userFee(address user) external view returns (uint256);
}
​
contract KyberSwapLIQ is Ownable{
using SafeMath for uint256;
using SafeERC20 for IERC20;
​
event AdminTokenRecovery(address tokenRecovered, uint256 amount);
​
mapping(address => bool) public whitelistRouter;
mapping(address => bool) public whitelistFromFee;
​
address payable public feeWallet;
address public feeEstimationContract;
address constant _ETH_ADDRESS_ = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
​
receive() external payable {}
​
//Compatible with ETH=>ERC20, ERC20=>ETH
function useKyberApiData(
address fromToken,
address toToken,
uint256 fromAmount,
address router,
bytes memory apiData
)
external
payable
{
require(whitelistRouter[router], "Router not whitelisted");
​
if (fromToken != _ETH_ADDRESS_) {
IERC20(fromToken).transferFrom(msg.sender, address(this), fromAmount);
_generalApproveMax(fromToken, router, fromAmount);
} else {
require(fromAmount == msg.value);
}
​
(bool success, ) = router.call{value: fromToken == _ETH_ADDRESS_ ? fromAmount : 0}(apiData);
require(success, "Swap failed");
​
// Handle fee, send fee to fee address
if(!whitelistFromFee[msg.sender]){
uint256 fee = ILiquidusFeeEstimation(feeEstimationContract).userFee(msg.sender);
// Charge fees based on holdings
if (fee != 0) {
_generalTransfer(toToken, feeWallet, _generalBalanceOf(toToken, address(this)).mul(fee).div(10000));
}
}
​
uint256 returnAmount = _generalBalanceOf(toToken, address(this));
​
address payable to = payable(msg.sender);
_generalTransfer(toToken, to, returnAmount);
}
​
​
function _generalApproveMax(
address token,
address to,
uint256 amount
) internal {
uint256 allowance = IERC20(token).allowance(address(this), to);
if (allowance < amount) {
if (allowance > 0) {
IERC20(token).safeApprove(to, 0);
}
IERC20(token).safeApprove(to, uint256(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff));
}
}
​
function _generalTransfer(
address token,
address payable to,
uint256 amount
) internal {
if (amount > 0) {
if (token == _ETH_ADDRESS_) {
to.transfer(amount);
} else {
IERC20(token).safeTransfer(to, amount);
}
}
}
​
function _generalBalanceOf(
address token,
address who
) internal view returns (uint256) {
if (token == _ETH_ADDRESS_ ) {
return who.balance;
} else {
return IERC20(token).balanceOf(who);
}
}
​
function setFees(address payable _feeWallet, address _feeEstimationContract) public onlyOwner {
feeWallet = _feeWallet;
feeEstimationContract = _feeEstimationContract;
}
​
function addWhitelistFromFee(address _account) public onlyOwner {
whitelistFromFee[_account] = true;
}
​
function removeWhitelistFromFee(address _account) public onlyOwner {
whitelistFromFee[_account] = false;
}
​
function addWhitelistRouter(address _router) public onlyOwner {
whitelistRouter[_router] = true;
}
​
function removeWhitelistRouter(address _router) public onlyOwner {
whitelistRouter[_router] = false;
}
​
function recoverWrongTokens(address _tokenAddress, uint256 _tokenAmount) external onlyOwner {
IERC20(_tokenAddress).safeTransfer(address(msg.sender), _tokenAmount);
emit AdminTokenRecovery(_tokenAddress, _tokenAmount);
}
}