Removed fee logics

This commit is contained in:
Thrilok Kumar 2020-08-09 21:37:13 +05:30
parent b14642548f
commit 7c6bc47737
2 changed files with 437 additions and 886 deletions

View File

@ -1,13 +1,12 @@
pragma solidity ^0.6.0; pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
// import files from common directory // import files from common directory
import { TokenInterface , MemoryInterface, EventInterface} from "../common/interfaces.sol"; import { TokenInterface , MemoryInterface, EventInterface} from "../common/interfaces.sol";
import { Stores } from "../common/stores.sol"; import { Stores } from "../common/stores.sol";
import { DSMath } from "../common/math.sol"; import { DSMath } from "../common/math.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface OneInchInterace { interface OneInchInterace {
function swap( function swap(
TokenInterface fromToken, TokenInterface fromToken,
@ -26,8 +25,52 @@ interface OneInchInterace {
returns (uint256 returnAmount); returns (uint256 returnAmount);
} }
interface OneProtoInterface {
function swapWithReferral(
TokenInterface fromToken,
TokenInterface destToken,
uint256 amount,
uint256 minReturn,
uint256[] calldata distribution,
uint256 flags, // See contants in IOneSplit.sol
address referral,
uint256 feePercent
) external payable returns(uint256);
function swapWithReferralMulti(
TokenInterface[] calldata tokens,
uint256 amount,
uint256 minReturn,
uint256[] calldata distribution,
uint256[] calldata flags,
address referral,
uint256 feePercent
) external payable returns(uint256 returnAmount);
function getExpectedReturn(
TokenInterface fromToken,
TokenInterface destToken,
uint256 amount,
uint256 parts,
uint256 flags // See constants in IOneSplit.sol
)
external
view
returns(
uint256 returnAmount,
uint256[] memory distribution
);
}
contract OneHelpers is Stores, DSMath { contract OneHelpers is Stores, DSMath {
using SafeERC20 for IERC20; /**
* @dev Return 1proto Address
*/
function getOneProtoAddress() internal pure returns (address payable) {
return 0x50FDA034C0Ce7a8f7EFDAebDA7Aa7cA21CC1267e;
}
/** /**
* @dev Return 1Inch Address * @dev Return 1Inch Address
*/ */
@ -70,33 +113,118 @@ contract OneHelpers is Stores, DSMath {
sellDec = address(sellAddr) == getEthAddr() ? 18 : sellAddr.decimals(); sellDec = address(sellAddr) == getEthAddr() ? 18 : sellAddr.decimals();
} }
function _transfer(address payable to, IERC20 token, uint _amt) internal { function getSlippageAmt(
address(token) == getEthAddr() ? TokenInterface _buyAddr,
to.transfer(_amt) : TokenInterface _sellAddr,
token.safeTransfer(to, _amt); uint _sellAmt,
uint unitAmt
) internal view returns(uint _slippageAmt) {
(uint _buyDec, uint _sellDec) = getTokensDec(_buyAddr, _sellAddr);
uint _sellAmt18 = convertTo18(_sellDec, _sellAmt);
_slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18));
} }
function takeFee( function convertToTokenInterface(address[] memory tokens) internal pure returns(TokenInterface[] memory) {
address token, TokenInterface[] memory _tokens = new TokenInterface[](tokens.length);
uint amount, for (uint i = 0; i < tokens.length; i++) {
address feeCollector, _tokens[i] = TokenInterface(tokens[i]);
uint feePercent
) internal returns (uint leftAmt, uint feeAmount){
if (feeCollector != address(0)) {
feeAmount = wmul(amount, feePercent);
leftAmt = sub(amount, feeAmount);
uint feeCollectorAmt = wmul(feeAmount, 3 * 10 ** 17);
uint restAmt = sub(feeAmount, feeCollectorAmt);
_transfer(payable(feeCollector), IERC20(token), feeCollectorAmt);
_transfer(payable(getReferralAddr()), IERC20(token), restAmt);
} else {
leftAmt = amount;
} }
return _tokens;
} }
} }
contract Resolver is OneHelpers { contract OneProtoResolver is OneHelpers {
struct OneProtoData {
TokenInterface sellToken;
TokenInterface buyToken;
uint _sellAmt;
uint _buyAmt;
uint unitAmt;
uint[] distribution;
uint disableDexes;
}
function oneProtoSwap(
OneProtoInterface oneProtoContract,
OneProtoData memory oneProtoData
) internal returns (uint buyAmt) {
TokenInterface _sellAddr = oneProtoData.sellToken;
TokenInterface _buyAddr = oneProtoData.buyToken;
uint _sellAmt = oneProtoData._sellAmt;
uint _slippageAmt = getSlippageAmt(_buyAddr, _sellAddr, _sellAmt, oneProtoData.unitAmt);
uint ethAmt;
if (address(_sellAddr) == getEthAddr()) {
ethAmt = _sellAmt;
} else {
_sellAddr.approve(address(oneProtoContract), _sellAmt);
}
uint initalBal = getTokenBal(_buyAddr);
oneProtoContract.swapWithReferral.value(ethAmt)(
_sellAddr,
_buyAddr,
_sellAmt,
_slippageAmt,
oneProtoData.distribution,
oneProtoData.disableDexes,
getReferralAddr(),
0
);
uint finalBal = getTokenBal(_buyAddr);
buyAmt = sub(finalBal, initalBal);
require(_slippageAmt <= buyAmt, "Too much slippage");
}
struct OneProtoMultiData {
address[] tokens;
TokenInterface sellToken;
TokenInterface buyToken;
uint _sellAmt;
uint _buyAmt;
uint unitAmt;
uint[] distribution;
uint[] disableDexes;
}
function oneProtoSwapMulti(OneProtoMultiData memory oneProtoData) internal returns (uint buyAmt) {
TokenInterface _sellAddr = oneProtoData.sellToken;
TokenInterface _buyAddr = oneProtoData.buyToken;
uint _sellAmt = oneProtoData._sellAmt;
uint _slippageAmt = getSlippageAmt(_buyAddr, _sellAddr, _sellAmt, oneProtoData.unitAmt);
OneProtoInterface oneSplitContract = OneProtoInterface(getOneProtoAddress());
uint ethAmt;
if (address(_sellAddr) == getEthAddr()) {
ethAmt = _sellAmt;
} else {
_sellAddr.approve(address(oneSplitContract), _sellAmt);
}
uint initalBal = getTokenBal(_buyAddr);
oneSplitContract.swapWithReferralMulti.value(ethAmt)(
convertToTokenInterface(oneProtoData.tokens),
_sellAmt,
_slippageAmt,
oneProtoData.distribution,
oneProtoData.disableDexes,
getReferralAddr(),
0
);
uint finalBal = getTokenBal(_buyAddr);
buyAmt = sub(finalBal, initalBal);
require(_slippageAmt <= buyAmt, "Too much slippage");
}
}
contract OneInchResolver is OneProtoResolver {
function checkOneInchSig(bytes memory callData) internal pure returns(bool isOk) { function checkOneInchSig(bytes memory callData) internal pure returns(bool isOk) {
bytes memory _data = callData; bytes memory _data = callData;
bytes4 sig; bytes4 sig;
@ -114,8 +242,6 @@ contract Resolver is OneHelpers {
uint _buyAmt; uint _buyAmt;
uint unitAmt; uint unitAmt;
bytes callData; bytes callData;
address feeCollector;
uint256 feeAmount;
} }
function oneInchSwap( function oneInchSwap(
@ -142,7 +268,7 @@ contract Resolver is OneHelpers {
} }
contract OneInchEventResolver is Resolver { contract OneProtoEventResolver is OneInchResolver {
event LogSell( event LogSell(
address indexed buyToken, address indexed buyToken,
address indexed sellToken, address indexed sellToken,
@ -152,75 +278,221 @@ contract OneInchEventResolver is Resolver {
uint256 setId uint256 setId
); );
event LogSellFee( function emitLogSell(
OneProtoData memory oneProtoData,
uint256 getId,
uint256 setId
) internal {
bytes32 _eventCode;
bytes memory _eventParam;
emit LogSell(
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
getId,
setId
);
_eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)");
_eventParam = abi.encode(
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
getId,
setId
);
emitEvent(_eventCode, _eventParam);
}
event LogSellTwo(
address indexed buyToken, address indexed buyToken,
address indexed sellToken, address indexed sellToken,
uint256 buyAmt, uint256 buyAmt,
uint256 sellAmt, uint256 sellAmt,
address indexed collector,
uint256 fee,
uint256 getId, uint256 getId,
uint256 setId uint256 setId
); );
function emitLogSell( function emitLogSellTwo(
OneProtoData memory oneProtoData,
uint256 getId,
uint256 setId
) internal {
bytes32 _eventCode;
bytes memory _eventParam;
emit LogSellTwo(
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
getId,
setId
);
_eventCode = keccak256("LogSellTwo(address,address,uint256,uint256,uint256,uint256)");
_eventParam = abi.encode(
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
getId,
setId
);
emitEvent(_eventCode, _eventParam);
}
event LogSellMulti(
address[] tokens,
address indexed buyToken,
address indexed sellToken,
uint256 buyAmt,
uint256 sellAmt,
uint256 getId,
uint256 setId
);
function emitLogSellMulti(
OneProtoMultiData memory oneProtoData,
uint256 getId,
uint256 setId
) internal {
bytes32 _eventCode;
bytes memory _eventParam;
emit LogSellMulti(
oneProtoData.tokens,
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
getId,
setId
);
_eventCode = keccak256("LogSellMulti(address[],address,address,uint256,uint256,uint256,uint256)");
_eventParam = abi.encode(
oneProtoData.tokens,
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
getId,
setId
);
emitEvent(_eventCode, _eventParam);
}
}
contract OneInchEventResolver is OneProtoEventResolver {
event LogSellThree(
address indexed buyToken,
address indexed sellToken,
uint256 buyAmt,
uint256 sellAmt,
uint256 getId,
uint256 setId
);
function emitLogSellThree(
OneInchData memory oneInchData, OneInchData memory oneInchData,
uint256 setId uint256 setId
) internal { ) internal {
bytes32 _eventCode; bytes32 _eventCode;
bytes memory _eventParam; bytes memory _eventParam;
if (oneInchData.feeCollector == address(0)) { emit LogSellThree(
emit LogSell( address(oneInchData.buyToken),
address(oneInchData.buyToken), address(oneInchData.sellToken),
address(oneInchData.sellToken), oneInchData._buyAmt,
oneInchData._buyAmt, oneInchData._sellAmt,
oneInchData._sellAmt, 0,
0, setId
setId );
); _eventCode = keccak256("LogSellThree(address,address,uint256,uint256,uint256,uint256)");
_eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)"); _eventParam = abi.encode(
_eventParam = abi.encode( address(oneInchData.buyToken),
address(oneInchData.buyToken), address(oneInchData.sellToken),
address(oneInchData.sellToken), oneInchData._buyAmt,
oneInchData._buyAmt, oneInchData._sellAmt,
oneInchData._sellAmt, 0,
0, setId
setId );
);
} else {
emit LogSellFee(
address(oneInchData.buyToken),
address(oneInchData.sellToken),
oneInchData._buyAmt,
oneInchData._sellAmt,
oneInchData.feeCollector,
oneInchData.feeAmount,
0,
setId
);
_eventCode = keccak256("LogSellFee(address,address,uint256,uint256,uint256,uint256)");
_eventParam = abi.encode(
address(oneInchData.buyToken),
address(oneInchData.sellToken),
oneInchData._buyAmt,
oneInchData._sellAmt,
oneInchData.feeCollector,
oneInchData.feeAmount,
0,
setId
);
}
emitEvent(_eventCode, _eventParam); emitEvent(_eventCode, _eventParam);
} }
} }
contract OneInchResolverHelpers is OneInchEventResolver { contract OneProtoResolverHelpers is OneInchEventResolver {
function _sell ( function _sell(
OneInchData memory oneInchData, OneProtoData memory oneProtoData,
uint feePercent, uint256 getId,
uint256 setId
) internal {
uint _sellAmt = getUint(getId, oneProtoData._sellAmt);
oneProtoData._sellAmt = _sellAmt == uint(-1) ?
getTokenBal(oneProtoData.sellToken) :
_sellAmt;
OneProtoInterface oneProtoContract = OneProtoInterface(getOneProtoAddress());
(, oneProtoData.distribution) = oneProtoContract.getExpectedReturn(
oneProtoData.sellToken,
oneProtoData.buyToken,
oneProtoData._sellAmt,
5,
0
);
oneProtoData._buyAmt = oneProtoSwap(
oneProtoContract,
oneProtoData
);
setUint(setId, oneProtoData._buyAmt);
emitLogSell(oneProtoData, getId, setId);
}
function _sellTwo(
OneProtoData memory oneProtoData,
uint getId,
uint setId
) internal {
uint _sellAmt = getUint(getId, oneProtoData._sellAmt);
oneProtoData._sellAmt = _sellAmt == uint(-1) ?
getTokenBal(oneProtoData.sellToken) :
_sellAmt;
oneProtoData._buyAmt = oneProtoSwap(
OneProtoInterface(getOneProtoAddress()),
oneProtoData
);
setUint(setId, oneProtoData._buyAmt);
emitLogSellTwo(oneProtoData, getId, setId);
}
function _sellMulti(
OneProtoMultiData memory oneProtoData,
uint getId,
uint setId
) internal {
uint _sellAmt = getUint(getId, oneProtoData._sellAmt);
oneProtoData._sellAmt = _sellAmt == uint(-1) ?
getTokenBal(oneProtoData.sellToken) :
_sellAmt;
oneProtoData._buyAmt = oneProtoSwapMulti(oneProtoData);
setUint(setId, oneProtoData._buyAmt);
emitLogSellMulti(oneProtoData, getId, setId);
}
}
contract OneInchResolverHelpers is OneProtoResolverHelpers {
function _sellThree(
OneInchData memory oneInchData,
uint setId uint setId
) internal { ) internal {
TokenInterface _buyAddr = oneInchData.buyToken;
TokenInterface _sellAddr = oneInchData.sellToken; TokenInterface _sellAddr = oneInchData.sellToken;
uint ethAmt; uint ethAmt;
@ -232,29 +504,21 @@ contract OneInchResolverHelpers is OneInchEventResolver {
require(checkOneInchSig(oneInchData.callData), "Not-swap-function"); require(checkOneInchSig(oneInchData.callData), "Not-swap-function");
uint buyAmt = oneInchSwap(oneInchData, ethAmt); oneInchData._buyAmt = oneInchSwap(oneInchData, ethAmt);
setUint(setId, oneInchData._buyAmt);
(uint leftBuyAmt, uint feeAmount) = takeFee( emitLogSellThree(oneInchData, setId);
address(_buyAddr),
buyAmt,
oneInchData.feeCollector,
feePercent
);
setUint(setId, leftBuyAmt);
oneInchData.feeAmount = feeAmount;
emitLogSell(oneInchData, setId);
} }
} }
contract OneInchResolver is OneInchResolverHelpers { contract OneProto is OneInchResolverHelpers {
/** /**
* @dev Sell ETH/ERC20_Token using 1inch. * @dev Sell ETH/ERC20_Token using 1proto.
* @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAddr selling token amount.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param sellAddr selling token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAmt selling token amount. * @param sellAmt selling token amount.
* @param unitAmt unit amount of buyAmt/sellAmt with slippage. * @param unitAmt unit amount of buyAmt/sellAmt with slippage.
* @param callData Data from 1inch API. * @param getId Get token amount at this ID from `InstaMemory` Contract.
* @param setId Set token amount at this ID in `InstaMemory` Contract. * @param setId Set token amount at this ID in `InstaMemory` Contract.
*/ */
function sell( function sell(
@ -262,23 +526,91 @@ contract OneInchResolver is OneInchResolverHelpers {
address sellAddr, address sellAddr,
uint sellAmt, uint sellAmt,
uint unitAmt, uint unitAmt,
bytes calldata callData, uint getId,
uint setId uint setId
) external payable { ) external payable {
OneInchData memory oneInchData = OneInchData({ OneProtoData memory oneProtoData = OneProtoData({
buyToken: TokenInterface(buyAddr), buyToken: TokenInterface(buyAddr),
sellToken: TokenInterface(sellAddr), sellToken: TokenInterface(sellAddr),
unitAmt: unitAmt,
callData: callData,
feeCollector: address(0),
_sellAmt: sellAmt, _sellAmt: sellAmt,
unitAmt: unitAmt,
distribution: new uint[](0),
_buyAmt: 0, _buyAmt: 0,
feeAmount: 0 disableDexes: 0
}); });
_sell(oneInchData, 0, setId); _sell(oneProtoData, getId, setId);
} }
/**
* @dev Sell ETH/ERC20_Token using 1proto using off-chain calculation.
* @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAddr selling token address.(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 {
OneProtoData memory oneProtoData = OneProtoData({
buyToken: TokenInterface(buyAddr),
sellToken: TokenInterface(sellAddr),
_sellAmt: sellAmt,
unitAmt: unitAmt,
distribution: distribution,
disableDexes: disableDexes,
_buyAmt: 0
});
_sellTwo(oneProtoData, getId, setId);
}
/**
* @dev Sell ETH/ERC20_Token using 1proto using muliple token.
* @param tokens array of tokens.
* @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 sellMulti(
address[] calldata tokens,
uint sellAmt,
uint unitAmt,
uint[] calldata distribution,
uint[] calldata disableDexes,
uint getId,
uint setId
) external payable {
OneProtoMultiData memory oneProtoData = OneProtoMultiData({
tokens: tokens,
buyToken: TokenInterface(address(tokens[tokens.length - 1])),
sellToken: TokenInterface(address(tokens[0])),
unitAmt: unitAmt,
distribution: distribution,
disableDexes: disableDexes,
_sellAmt: sellAmt,
_buyAmt: 0
});
_sellMulti(oneProtoData, getId, setId);
}
}
contract OneInch is OneProto {
/** /**
* @dev Sell ETH/ERC20_Token using 1inch. * @dev Sell ETH/ERC20_Token using 1inch.
* @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
@ -286,38 +618,29 @@ contract OneInchResolver is OneInchResolverHelpers {
* @param sellAmt selling token amount. * @param sellAmt selling token amount.
* @param unitAmt unit amount of buyAmt/sellAmt with slippage. * @param unitAmt unit amount of buyAmt/sellAmt with slippage.
* @param callData Data from 1inch API. * @param callData Data from 1inch API.
* @param feeCollector Fee amount to transfer.
* @param feePercent Fee percentage on buyAmt.
* @param setId Set token amount at this ID in `InstaMemory` Contract. * @param setId Set token amount at this ID in `InstaMemory` Contract.
*/ */
function sellFee( function sellThree(
address buyAddr, address buyAddr,
address sellAddr, address sellAddr,
uint sellAmt, uint sellAmt,
uint unitAmt, uint unitAmt,
bytes calldata callData, bytes calldata callData,
address feeCollector,
uint feePercent,
uint setId uint setId
) external payable { ) external payable {
require(feePercent > 0 && feePercent <= 2 * 10 ** 16, "Fee more than 2%");
require(feeCollector != address(0), "feeCollector is not vaild address");
OneInchData memory oneInchData = OneInchData({ OneInchData memory oneInchData = OneInchData({
buyToken: TokenInterface(buyAddr), buyToken: TokenInterface(buyAddr),
sellToken: TokenInterface(sellAddr), sellToken: TokenInterface(sellAddr),
_sellAmt: sellAmt,
unitAmt: unitAmt, unitAmt: unitAmt,
callData: callData, callData: callData,
feeCollector: feeCollector, _sellAmt: sellAmt,
_buyAmt: 0, _buyAmt: 0
feeAmount: 0
}); });
_sell(oneInchData, feePercent, setId); _sellThree(oneInchData, setId);
} }
} }
contract ConnectOneInchOnChain is OneInchResolver { contract ConnectOne is OneInch {
string public name = "1inch-Onchain-v1"; string public name = "1inch-1proto-v1";
} }

View File

@ -1,772 +0,0 @@
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
// 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";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface OneProtoInterface {
function swapWithReferral(
TokenInterface fromToken,
TokenInterface destToken,
uint256 amount,
uint256 minReturn,
uint256[] calldata distribution,
uint256 flags, // See contants in IOneSplit.sol
address referral,
uint256 feePercent
) external payable returns(uint256);
function swapWithReferralMulti(
TokenInterface[] calldata tokens,
uint256 amount,
uint256 minReturn,
uint256[] calldata distribution,
uint256[] calldata flags,
address referral,
uint256 feePercent
) external payable returns(uint256 returnAmount);
function getExpectedReturn(
TokenInterface fromToken,
TokenInterface destToken,
uint256 amount,
uint256 parts,
uint256 flags // See constants in IOneSplit.sol
)
external
view
returns(
uint256 returnAmount,
uint256[] memory distribution
);
}
contract OneHelpers is Stores, DSMath {
using SafeERC20 for IERC20;
/**
* @dev Return 1proto Address
*/
function getOneProtoAddress() internal virtual view returns (address payable) {
return 0x50FDA034C0Ce7a8f7EFDAebDA7Aa7cA21CC1267e;
}
function getReferralAddr() internal pure returns (address) {
return 0xa7615CD307F323172331865181DC8b80a2834324; // TODO - change address
}
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();
}
function getSlippageAmt(
TokenInterface _buyAddr,
TokenInterface _sellAddr,
uint _sellAmt,
uint unitAmt
) internal view returns(uint _slippageAmt) {
(uint _buyDec, uint _sellDec) = getTokensDec(_buyAddr, _sellAddr);
uint _sellAmt18 = convertTo18(_sellDec, _sellAmt);
_slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18));
}
function convertToTokenInterface(address[] memory tokens) internal pure returns(TokenInterface[] memory) {
TokenInterface[] memory _tokens = new TokenInterface[](tokens.length);
for (uint i = 0; i < tokens.length; i++) {
_tokens[i] = TokenInterface(tokens[i]);
}
return _tokens;
}
function _transfer(address payable to, IERC20 token, uint _amt) internal {
address(token) == getEthAddr() ?
to.transfer(_amt) :
token.safeTransfer(to, _amt);
}
function takeFee(
address token,
uint amount,
address feeCollector,
uint feePercent
) internal returns (uint leftAmt, uint feeAmount){
if (feeCollector != address(0)) {
feeAmount = wmul(amount, feePercent);
leftAmt = sub(amount, feeAmount);
uint feeCollectorAmt = wmul(feeAmount, 7 * 10 ** 17); // 70% to feeCollector
uint restAmt = sub(feeAmount, feeCollectorAmt); // rest 30%
IERC20 tokenContract = IERC20(token);
_transfer(payable(feeCollector), tokenContract, feeCollectorAmt);
_transfer(payable(getReferralAddr()), tokenContract, restAmt);
} else {
leftAmt = amount;
}
}
}
contract Resolver is OneHelpers {
struct OneProtoData {
TokenInterface sellToken;
TokenInterface buyToken;
uint _sellAmt;
uint _buyAmt;
uint unitAmt;
address feeCollector;
uint256 feeAmount;
uint[] distribution;
uint disableDexes;
}
function oneProtoSwap(
OneProtoInterface oneProtoContract,
OneProtoData memory oneProtoData
) internal returns (uint buyAmt) {
TokenInterface _sellAddr = oneProtoData.sellToken;
TokenInterface _buyAddr = oneProtoData.buyToken;
uint _sellAmt = oneProtoData._sellAmt;
uint _slippageAmt = getSlippageAmt(_buyAddr, _sellAddr, _sellAmt, oneProtoData.unitAmt);
uint ethAmt;
if (address(_sellAddr) == getEthAddr()) {
ethAmt = _sellAmt;
} else {
_sellAddr.approve(address(oneProtoContract), _sellAmt);
}
uint initalBal = getTokenBal(_buyAddr);
oneProtoContract.swapWithReferral.value(ethAmt)(
_sellAddr,
_buyAddr,
_sellAmt,
_slippageAmt,
oneProtoData.distribution,
oneProtoData.disableDexes,
getReferralAddr(),
0
);
uint finalBal = getTokenBal(_buyAddr);
buyAmt = sub(finalBal, initalBal);
require(_slippageAmt <= buyAmt, "Too much slippage");
}
struct OneProtoMultiData {
address[] tokens;
TokenInterface sellToken;
TokenInterface buyToken;
uint _sellAmt;
uint _buyAmt;
uint unitAmt;
address feeCollector;
uint256 feeAmount;
uint[] distribution;
uint[] disableDexes;
}
function oneProtoSwapMulti(OneProtoMultiData memory oneProtoData) internal returns (uint buyAmt) {
TokenInterface _sellAddr = oneProtoData.sellToken;
TokenInterface _buyAddr = oneProtoData.buyToken;
uint _sellAmt = oneProtoData._sellAmt;
uint _slippageAmt = getSlippageAmt(_buyAddr, _sellAddr, _sellAmt, oneProtoData.unitAmt);
OneProtoInterface oneSplitContract = OneProtoInterface(getOneProtoAddress());
uint ethAmt;
if (address(_sellAddr) == getEthAddr()) {
ethAmt = _sellAmt;
} else {
_sellAddr.approve(address(oneSplitContract), _sellAmt);
}
uint initalBal = getTokenBal(_buyAddr);
oneSplitContract.swapWithReferralMulti.value(ethAmt)(
convertToTokenInterface(oneProtoData.tokens),
_sellAmt,
_slippageAmt,
oneProtoData.distribution,
oneProtoData.disableDexes,
getReferralAddr(),
0
);
uint finalBal = getTokenBal(_buyAddr);
buyAmt = sub(finalBal, initalBal);
require(_slippageAmt <= buyAmt, "Too much slippage");
}
}
contract OneProtoEventResolver is Resolver {
event LogSell(
address indexed buyToken,
address indexed sellToken,
uint256 buyAmt,
uint256 sellAmt,
uint256 getId,
uint256 setId
);
event LogSellFee(
address indexed buyToken,
address indexed sellToken,
uint256 buyAmt,
uint256 sellAmt,
address indexed feeCollector,
uint256 feeAmount,
uint256 getId,
uint256 setId
);
function emitLogSell(
OneProtoData memory oneProtoData,
uint256 getId,
uint256 setId
) internal {
bytes32 _eventCode;
bytes memory _eventParam;
if (oneProtoData.feeCollector == address(0)) {
emit LogSell(
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
getId,
setId
);
_eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)");
_eventParam = abi.encode(
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
getId,
setId
);
} else {
emit LogSellFee(
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
oneProtoData.feeCollector,
oneProtoData.feeAmount,
getId,
setId
);
_eventCode = keccak256("LogSellFee(address,address,uint256,uint256,address,uint256,uint256,uint256)");
_eventParam = abi.encode(
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
oneProtoData.feeCollector,
oneProtoData.feeAmount,
getId,
setId
);
}
emitEvent(_eventCode, _eventParam);
}
event LogSellTwo(
address indexed buyToken,
address indexed sellToken,
uint256 buyAmt,
uint256 sellAmt,
uint256 getId,
uint256 setId
);
event LogSellFeeTwo(
address indexed buyToken,
address indexed sellToken,
uint256 buyAmt,
uint256 sellAmt,
address indexed feeCollector,
uint256 feeAmount,
uint256 getId,
uint256 setId
);
function emitLogSellTwo(
OneProtoData memory oneProtoData,
uint256 getId,
uint256 setId
) internal {
bytes32 _eventCode;
bytes memory _eventParam;
if (oneProtoData.feeCollector == address(0)) {
emit LogSellTwo(
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
getId,
setId
);
_eventCode = keccak256("LogSellTwo(address,address,uint256,uint256,uint256,uint256)");
_eventParam = abi.encode(
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
getId,
setId
);
} else {
emit LogSellFeeTwo(
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
oneProtoData.feeCollector,
oneProtoData.feeAmount,
getId,
setId
);
_eventCode = keccak256("LogSellFeeTwo(address,address,uint256,uint256,address,uint256,uint256,uint256)");
_eventParam = abi.encode(
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
oneProtoData.feeCollector,
oneProtoData.feeAmount,
getId,
setId
);
}
emitEvent(_eventCode, _eventParam);
}
event LogSellMulti(
address[] tokens,
address indexed buyToken,
address indexed sellToken,
uint256 buyAmt,
uint256 sellAmt,
uint256 getId,
uint256 setId
);
event LogSellFeeMulti(
address[] tokens,
address indexed buyToken,
address indexed sellToken,
uint256 buyAmt,
uint256 sellAmt,
address indexed feeCollector,
uint256 feeAmount,
uint256 getId,
uint256 setId
);
function emitLogSellMulti(
OneProtoMultiData memory oneProtoData,
uint256 getId,
uint256 setId
) internal {
bytes32 _eventCode;
bytes memory _eventParam;
if (oneProtoData.feeCollector == address(0)) {
emit LogSellMulti(
oneProtoData.tokens,
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
getId,
setId
);
_eventCode = keccak256("LogSellMulti(address[],address,address,uint256,uint256,uint256,uint256)");
_eventParam = abi.encode(
oneProtoData.tokens,
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
getId,
setId
);
} else {
emit LogSellFeeMulti(
oneProtoData.tokens,
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
oneProtoData.feeCollector,
oneProtoData.feeAmount,
getId,
setId
);
_eventCode = keccak256("LogSellFeeMulti(address[],address,address,uint256,uint256,address,uint256,uint256,uint256)");
_eventParam = abi.encode(
oneProtoData.tokens,
address(oneProtoData.buyToken),
address(oneProtoData.sellToken),
oneProtoData._buyAmt,
oneProtoData._sellAmt,
oneProtoData.feeCollector,
oneProtoData.feeAmount,
getId,
setId
);
}
emitEvent(_eventCode, _eventParam);
}
}
contract OneProtoResolverHelpers is OneProtoEventResolver {
function _sell(
OneProtoData memory oneProtoData,
uint256 feePercent,
uint256 getId,
uint256 setId
) internal {
uint _sellAmt = getUint(getId, oneProtoData._sellAmt);
oneProtoData._sellAmt = _sellAmt == uint(-1) ?
getTokenBal(oneProtoData.sellToken) :
_sellAmt;
OneProtoInterface oneProtoContract = OneProtoInterface(getOneProtoAddress());
(, oneProtoData.distribution) = oneProtoContract.getExpectedReturn(
oneProtoData.sellToken,
oneProtoData.buyToken,
oneProtoData._sellAmt,
5,
0
);
oneProtoData._buyAmt = oneProtoSwap(
oneProtoContract,
oneProtoData
);
(uint leftBuyAmt, uint feeAmount) = takeFee(
address(oneProtoData.buyToken),
oneProtoData._buyAmt,
oneProtoData.feeCollector,
feePercent
);
setUint(setId, leftBuyAmt);
oneProtoData.feeAmount = feeAmount;
emitLogSell(oneProtoData, getId, setId);
}
function _sellTwo(
OneProtoData memory oneProtoData,
uint256 feePercent,
uint getId,
uint setId
) internal {
uint _sellAmt = getUint(getId, oneProtoData._sellAmt);
oneProtoData._sellAmt = _sellAmt == uint(-1) ?
getTokenBal(oneProtoData.sellToken) :
_sellAmt;
oneProtoData._buyAmt = oneProtoSwap(
OneProtoInterface(getOneProtoAddress()),
oneProtoData
);
(uint leftBuyAmt, uint feeAmount) = takeFee(
address(oneProtoData.buyToken),
oneProtoData._buyAmt,
oneProtoData.feeCollector,
feePercent
);
setUint(setId, leftBuyAmt);
oneProtoData.feeAmount = feeAmount;
emitLogSellTwo(oneProtoData, getId, setId);
}
function _sellMulti(
OneProtoMultiData memory oneProtoData,
uint256 feePercent,
uint getId,
uint setId
) internal {
uint _sellAmt = getUint(getId, oneProtoData._sellAmt);
oneProtoData._sellAmt = _sellAmt == uint(-1) ?
getTokenBal(oneProtoData.sellToken) :
_sellAmt;
oneProtoData._buyAmt = oneProtoSwapMulti(oneProtoData);
uint leftBuyAmt;
(leftBuyAmt, oneProtoData.feeAmount) = takeFee(
address(oneProtoData.buyToken),
oneProtoData._buyAmt,
oneProtoData.feeCollector,
feePercent
);
setUint(setId, leftBuyAmt);
emitLogSellMulti(oneProtoData, getId, setId);
}
}
contract OneProtoResolver is OneProtoResolverHelpers {
/**
* @dev Sell ETH/ERC20_Token using 1proto.
* @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAddr selling token address.(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 {
OneProtoData memory oneProtoData = OneProtoData({
buyToken: TokenInterface(buyAddr),
sellToken: TokenInterface(sellAddr),
_sellAmt: sellAmt,
unitAmt: unitAmt,
distribution: new uint[](0),
feeCollector: address(0),
_buyAmt: 0,
disableDexes: 0,
feeAmount: 0
});
_sell(oneProtoData, 0, getId, setId);
}
/**
* @dev Sell ETH/ERC20_Token using 1proto on-chain calculation.
* @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAddr selling token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAmt selling token amount.
* @param unitAmt unit amount of buyAmt/sellAmt with slippage.
* @param feeCollector Fee amount to transfer.
* @param feePercent Fee percentage on buyAmt.
* @param getId Get token amount at this ID from `InstaMemory` Contract.
* @param setId Set token amount at this ID in `InstaMemory` Contract.
*/
function sellFee(
address buyAddr,
address sellAddr,
uint sellAmt,
uint unitAmt,
address feeCollector,
uint feePercent,
uint getId,
uint setId
) external payable {
require(feePercent > 0 && feePercent <= 2 * 10 ** 16, "Fee more than 2%");
require(feeCollector != address(0), "feeCollector is not vaild address");
OneProtoData memory oneProtoData = OneProtoData({
buyToken: TokenInterface(buyAddr),
sellToken: TokenInterface(sellAddr),
_sellAmt: sellAmt,
unitAmt: unitAmt,
distribution: new uint[](0),
feeCollector: feeCollector,
_buyAmt: 0,
disableDexes: 0,
feeAmount: 0
});
_sell(oneProtoData, feePercent, getId, setId);
}
/**
* @dev Sell ETH/ERC20_Token using 1proto using off-chain calculation.
* @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAddr selling token address.(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 {
OneProtoData memory oneProtoData = OneProtoData({
buyToken: TokenInterface(buyAddr),
sellToken: TokenInterface(sellAddr),
_sellAmt: sellAmt,
unitAmt: unitAmt,
distribution: distribution,
disableDexes: disableDexes,
feeCollector: address(0),
_buyAmt: 0,
feeAmount: 0
});
_sellTwo(oneProtoData, 0, getId, setId);
}
/**
* @dev Sell ETH/ERC20_Token using 1proto.
* @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param sellAddr selling token address.(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 feeCollector Fee amount to transfer.
* @param feePercent Fee percentage on buyAmt.
* @param getId Get token amount at this ID from `InstaMemory` Contract.
* @param setId Set token amount at this ID in `InstaMemory` Contract.
*/
function sellFeeTwo(
address buyAddr,
address sellAddr,
uint sellAmt,
uint unitAmt,
uint[] calldata distribution,
uint disableDexes,
address feeCollector,
uint feePercent,
uint getId,
uint setId
) external payable {
require(feePercent > 0 && feePercent <= 2 * 10 ** 16, "Fee more than 2%");
require(feeCollector != address(0), "feeCollector is not vaild address");
OneProtoData memory oneProtoData = OneProtoData({
buyToken: TokenInterface(buyAddr),
sellToken: TokenInterface(sellAddr),
_sellAmt: sellAmt,
unitAmt: unitAmt,
distribution: distribution,
disableDexes: disableDexes,
feeCollector: feeCollector,
_buyAmt: 0,
feeAmount: 0
});
_sellTwo(oneProtoData, feePercent, getId, setId);
}
/**
* @dev Sell ETH/ERC20_Token using 1proto using muliple token.
* @param tokens array of tokens.
* @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 sellMulti(
address[] calldata tokens,
uint sellAmt,
uint unitAmt,
uint[] calldata distribution,
uint[] calldata disableDexes,
uint getId,
uint setId
) external payable {
OneProtoMultiData memory oneProtoData = OneProtoMultiData({
tokens: tokens,
buyToken: TokenInterface(address(tokens[tokens.length - 1])),
sellToken: TokenInterface(address(tokens[0])),
unitAmt: unitAmt,
distribution: distribution,
disableDexes: disableDexes,
_sellAmt: sellAmt,
feeCollector: address(0),
_buyAmt: 0,
feeAmount: 0
});
_sellMulti(oneProtoData, 0, getId, setId);
}
/**
* @dev Sell ETH/ERC20_Token using 1proto using muliple token.
* @param tokens buying token address.(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 feeCollector Fee amount to transfer.
* @param feePercent Fee percentage on buyAmt.
* @param getId Get token amount at this ID from `InstaMemory` Contract.
* @param setId Set token amount at this ID in `InstaMemory` Contract.
*/
function sellFeeMulti(
address[] calldata tokens,
uint sellAmt,
uint unitAmt,
uint[] calldata distribution,
uint[] calldata disableDexes,
address feeCollector,
uint feePercent,
uint getId,
uint setId
) external payable {
require(feePercent > 0 && feePercent <= 2 * 10 ** 16, "Fee more than 2%");
require(feeCollector != address(0), "feeCollector is not vaild address");
TokenInterface buyToken = TokenInterface(address(tokens[tokens.length - 1]));
OneProtoMultiData memory oneProtoData = OneProtoMultiData({
tokens: tokens,
buyToken: buyToken,
sellToken: TokenInterface(address(tokens[0])),
_sellAmt: sellAmt,
unitAmt: unitAmt,
distribution: distribution,
disableDexes: disableDexes,
feeCollector: feeCollector,
_buyAmt: 0,
feeAmount: 0
});
_sellMulti(oneProtoData, feePercent, getId, setId);
}
}
contract ConnectOneInchOffChain is OneProtoResolver {
string public name = "1inch-OffChain-v1";
}