dsa-connectors-old/contracts/connectors/1inch.sol
2020-05-11 05:48:40 +05:30

340 lines
11 KiB
Solidity

pragma solidity ^0.6.0;
// import files from common directory
import { TokenInterface , MemoryInterface, EventInterface} from "../common/interfaces.sol";
import { Stores } from "../common/stores.sol";
import { DSMath } from "../common/math.sol";
interface OneInchInterace {
function swap(
TokenInterface fromToken,
TokenInterface toToken,
uint256 fromTokenAmount,
uint256 minReturnAmount,
uint256 guaranteedAmount,
address payable referrer,
address[] calldata callAddresses,
bytes calldata callDataConcat,
uint256[] calldata starts,
uint256[] calldata gasLimitsAndValues
)
external
payable
returns (uint256 returnAmount);
}
interface OneSplitInterface {
function swap(
TokenInterface fromToken,
TokenInterface toToken,
uint256 amount,
uint256 minReturn,
uint256[] calldata distribution,
uint256 disableFlags
) external payable;
function getExpectedReturn(
TokenInterface fromToken,
TokenInterface toToken,
uint256 amount,
uint256 parts,
uint256 disableFlags
)
external
view
returns(
uint256 returnAmount,
uint256[] memory distribution
);
}
contract OneHelpers is Stores, DSMath {
/**
* @dev Return 1Inch Address
*/
function getOneInchAddress() internal pure returns (address) {
return 0x11111254369792b2Ca5d084aB5eEA397cA8fa48B;
}
/**
* @dev Return 1Split Address
*/
function getOneSplitAddress() internal pure returns (address payable) {
return 0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E;
}
/**
* @dev Return 1Split Token Taker Address
*/
function getOneSplitTokenTaker() internal pure returns (address payable) {
return 0xE4C9194962532fEB467DCe8b3d42419641c6eD2E;
}
/**
* @dev Return 1Split swap function sig
*/
function getOneSplitSig() internal pure returns (bytes4) {
return 0xf88309d7;
}
function convert18ToDec(uint _dec, uint256 _amt) internal pure returns (uint256 amt) {
amt = (_amt / 10 ** (18 - _dec));
}
function convertTo18(uint _dec, uint256 _amt) internal pure returns (uint256 amt) {
amt = mul(_amt, 10 ** (18 - _dec));
}
function getTokenBal(TokenInterface token) internal view returns(uint _amt) {
_amt = address(token) == getEthAddr() ? address(this).balance : token.balanceOf(address(this));
}
function getTokensDec(TokenInterface buyAddr, TokenInterface sellAddr) internal view returns(uint buyDec, uint sellDec) {
buyDec = address(buyAddr) == getEthAddr() ? 18 : buyAddr.decimals();
sellDec = address(sellAddr) == getEthAddr() ? 18 : sellAddr.decimals();
}
}
contract Resolver is OneHelpers {
function checkOneInchSig(bytes memory callData) internal pure returns(bool isOk) {
bytes memory _data = callData;
bytes4 sig;
// solium-disable-next-line security/no-inline-assembly
assembly {
sig := mload(add(_data, 32))
}
isOk = sig == getOneSplitSig();
}
function oneSplitSwap(
OneSplitInterface oneSplitContract,
TokenInterface _sellAddr,
TokenInterface _buyAddr,
uint _sellAmt,
uint unitAmt,
uint[] memory distribution,
uint disableDexes
) internal returns (uint buyAmt){
(uint _buyDec, uint _sellDec) = getTokensDec(_buyAddr, _sellAddr);
uint _sellAmt18 = convertTo18(_sellDec, _sellAmt);
uint _slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18));
uint ethAmt;
if (address(_sellAddr) == getEthAddr()) {
ethAmt = _sellAmt;
} else {
_sellAddr.approve(address(oneSplitContract), _sellAmt);
}
uint initalBal = getTokenBal(_buyAddr);
oneSplitContract.swap.value(ethAmt)(
_sellAddr,
_buyAddr,
_sellAmt,
_slippageAmt,
distribution,
disableDexes
);
uint finalBal = getTokenBal(_buyAddr);
buyAmt = sub(finalBal, initalBal);
require(_slippageAmt <= buyAmt, "Too much slippage");
}
function oneInchSwap(
TokenInterface _buyAddr,
TokenInterface _sellAddr,
bytes memory callData,
uint sellAmt,
uint unitAmt,
uint ethAmt
) internal returns (uint buyAmt) {
(uint _buyDec, uint _sellDec) = getTokensDec(_buyAddr, _sellAddr);
uint _sellAmt18 = convertTo18(_sellDec, sellAmt);
uint _slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18));
uint initalBal = getTokenBal(_buyAddr);
// solium-disable-next-line security/no-call-value
(bool success, ) = address(getOneInchAddress()).call.value(ethAmt)(callData);
if (!success) revert("1Inch-swap-failed");
uint finalBal = getTokenBal(_buyAddr);
buyAmt = sub(finalBal, initalBal);
require(_slippageAmt <= buyAmt, "Too much slippage");
}
}
contract BasicResolver is Resolver {
event LogSell(
address indexed buyToken,
address indexed sellToken,
uint256 buyAmt,
uint256 sellAmt,
uint256 getId,
uint256 setId
);
event LogSellTwo(
address indexed buyToken,
address indexed sellToken,
uint256 buyAmt,
uint256 sellAmt,
uint256 getId,
uint256 setId
);
event LogSellThree(
address indexed buyToken,
address indexed sellToken,
uint256 buyAmt,
uint256 sellAmt,
uint256 getId,
uint256 setId
);
/**
* @dev Sell ETH/ERC20_Token using 1split.
* @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAddr selling token amount.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAmt selling token amount.
* @param unitAmt unit amount of buyAmt/sellAmt with slippage.
* @param getId Get token amount at this ID from `InstaMemory` Contract.
* @param setId Set token amount at this ID in `InstaMemory` Contract.
*/
function sell(
address buyAddr,
address sellAddr,
uint sellAmt,
uint unitAmt,
uint getId,
uint setId
) external payable {
uint _sellAmt = getUint(getId, sellAmt);
TokenInterface _buyAddr = TokenInterface(buyAddr);
TokenInterface _sellAddr = TokenInterface(sellAddr);
_sellAmt = _sellAmt == uint(-1) ? getTokenBal(_sellAddr) : _sellAmt;
OneSplitInterface oneSplitContract = OneSplitInterface(getOneSplitAddress());
(, uint[] memory distribution) = oneSplitContract.getExpectedReturn(
_sellAddr,
_buyAddr,
_sellAmt,
5,
0
);
uint _buyAmt = oneSplitSwap(
oneSplitContract,
_sellAddr,
_buyAddr,
_sellAmt,
unitAmt,
distribution,
0
);
setUint(setId, _buyAmt);
emit LogSell(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId);
bytes32 _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)");
bytes memory _eventParam = abi.encode(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId);
emitEvent(_eventCode, _eventParam);
}
/**
* @dev Sell ETH/ERC20_Token using 1split.
* @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAddr selling token amount.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAmt selling token amount.
* @param unitAmt unit amount of buyAmt/sellAmt with slippage.
* @param distribution distribution of swap across different dex.
* @param disableDexes disable a dex. (To disable none: 0)
* @param getId Get token amount at this ID from `InstaMemory` Contract.
* @param setId Set token amount at this ID in `InstaMemory` Contract.
*/
function sellTwo(
address buyAddr,
address sellAddr,
uint sellAmt,
uint unitAmt,
uint[] calldata distribution,
uint disableDexes,
uint getId,
uint setId
) external payable {
uint _sellAmt = getUint(getId, sellAmt);
TokenInterface _buyAddr = TokenInterface(buyAddr);
TokenInterface _sellAddr = TokenInterface(sellAddr);
_sellAmt = _sellAmt == uint(-1) ? getTokenBal(_sellAddr) : _sellAmt;
uint _buyAmt = oneSplitSwap(
OneSplitInterface(getOneSplitAddress()),
_sellAddr,
_buyAddr,
_sellAmt,
unitAmt,
distribution,
disableDexes
);
setUint(setId, _buyAmt);
emit LogSellTwo(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId);
bytes32 _eventCode = keccak256("LogSellTwo(address,address,uint256,uint256,uint256,uint256)");
bytes memory _eventParam = abi.encode(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId);
emitEvent(_eventCode, _eventParam);
}
/**
* @dev Sell ETH/ERC20_Token using 1split.
* @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAddr selling token amount.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAmt selling token amount.
* @param unitAmt unit amount of buyAmt/sellAmt with slippage.
* @param callData Data from 1inch API.
* @param setId Set token amount at this ID in `InstaMemory` Contract.
*/
function sellThree(
address buyAddr,
address sellAddr,
uint sellAmt,
uint unitAmt,
bytes calldata callData,
uint setId
) external payable {
TokenInterface _buyAddr = TokenInterface(buyAddr);
TokenInterface _sellAddr = TokenInterface(sellAddr);
uint ethAmt;
if (address(_sellAddr) == getEthAddr()) {
ethAmt = sellAmt;
} else {
TokenInterface(_sellAddr).approve(getOneSplitTokenTaker(), sellAmt);
}
require(checkOneInchSig(callData), "Not-swap-function");
uint buyAmt = oneInchSwap(_buyAddr, _sellAddr, callData, sellAmt, unitAmt, ethAmt);
setUint(setId, buyAmt);
emit LogSellThree(address(_buyAddr), address(_sellAddr), buyAmt, sellAmt, 0, setId);
bytes32 _eventCode = keccak256("LogSellThree(address,address,uint256,uint256,uint256,uint256)");
bytes memory _eventParam = abi.encode(address(_buyAddr), address(_sellAddr), buyAmt, sellAmt, 0, setId);
emitEvent(_eventCode, _eventParam);
}
}
contract ConnectOne is BasicResolver {
string public name = "1Inch-1Split-v1";
}