Created
January 10, 2020 17:44
-
-
Save viraj124/3554bdc7d34dd9937eeba9c7f7a765bc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.5.7; | |
contract KyberInterface { | |
function trade( | |
address src, | |
uint srcAmount, | |
address dest, | |
address destAddress, | |
uint maxDestAmount, | |
uint minConversionRate, | |
address walletId | |
) public payable returns (uint); | |
function getExpectedRate( | |
address src, | |
address dest, | |
uint srcQty | |
) public view returns (uint, uint); | |
} | |
contract Helper { | |
/** | |
* @dev get ethereum address for trade | |
*/ | |
function getAddressETH() public pure returns (address eth) { | |
eth = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; | |
} | |
/** | |
* @dev get kyber proxy address | |
*/ | |
function getAddressKyber() public pure returns (address kyber) { | |
kyber = 0x818E6FECD516Ecc3849DAf6845e3EC868087B755; | |
} | |
/** | |
* @dev get admin address | |
*/ | |
function getAddressAdmin() public pure returns (address admin) { | |
admin = 0x7284a8451d9a0e7Dc62B3a71C0593eA2eC5c5638; | |
} | |
/** | |
* @dev gets ETH & token balance | |
* @param src is the token being sold | |
* @return ethBal - if not erc20, eth balance | |
* @return tknBal - if not eth, erc20 balance | |
*/ | |
function getBal(address src, address _owner) public view returns (uint, uint) { | |
uint tknBal; | |
if (src != getAddressETH()) { | |
tknBal = IERC20(src).balanceOf(address(_owner)); | |
} | |
return (address(_owner).balance, tknBal); | |
} | |
/** | |
* @dev getting rates from Kyber | |
* @param src is the token being sold | |
* @param dest is the token being bought | |
* @param srcAmt is the amount of token being sold | |
* @return expectedRate - the current rate | |
* @return slippageRate - rate with 3% slippage | |
*/ | |
function getExpectedRate( | |
address src, | |
address dest, | |
uint srcAmt | |
) public view returns ( | |
uint expectedRate, | |
uint slippageRate | |
) | |
{ | |
(expectedRate,) = KyberInterface(getAddressKyber()).getExpectedRate(src, dest, srcAmt); | |
slippageRate = (expectedRate / 100) * 99; // changing slippage rate upto 99% | |
} | |
/** | |
* @dev fetching token from the trader if ERC20 | |
* @param trader is the trader | |
* @param src is the token which is being sold | |
* @param srcAmt is the amount of token being sold | |
*/ | |
function getToken(address trader, address src, uint srcAmt) internal returns (uint ethQty) { | |
if (src == getAddressETH()) { | |
require(msg.value == srcAmt, "not-enough-src"); | |
ethQty = srcAmt; | |
} else { | |
IERC20 tknContract = IERC20(src); | |
setApproval(tknContract, srcAmt); | |
tknContract.transferFrom(trader, address(this), srcAmt); | |
} | |
} | |
/** | |
* @dev setting allowance to kyber for the "user proxy" if required | |
* @param tknContract is the token | |
* @param srcAmt is the amount of token to sell | |
*/ | |
function setApproval(IERC20 tknContract, uint srcAmt) internal returns (uint) { | |
uint tokenAllowance = tknContract.allowance(address(this), getAddressKyber()); | |
if (srcAmt > tokenAllowance) { | |
tknContract.approve(getAddressKyber(), 2**255); | |
} | |
} | |
} | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (uint256); | |
/** | |
* @dev Moves `amount` tokens from the caller's account to `recipient`. | |
* | |
* Returns a boolean value indicating whether the operation succeeded. | |
* | |
* Emits a {Transfer} event. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Returns the remaining number of tokens that `spender` will be | |
* allowed to spend on behalf of `owner` through {transferFrom}. This is | |
* zero by default. | |
* | |
* This value changes when {approve} or {transferFrom} are called. | |
*/ | |
function allowance(address owner, address spender) external view returns (uint256); | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens. | |
* | |
* Returns a boolean value indicating whether the operation succeeded. | |
* | |
* IMPORTANT: Beware that changing an allowance with this method brings the risk | |
* that someone may use both the old and the new allowance by unfortunate | |
* transaction ordering. One possible solution to mitigate this race | |
* condition is to first reduce the spender's allowance to 0 and set the | |
* desired value afterwards: | |
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 | |
* | |
* Emits an {Approval} event. | |
*/ | |
function approve(address spender, uint256 amount) external returns (bool); | |
/** | |
* @dev Moves `amount` tokens from `sender` to `recipient` using the | |
* allowance mechanism. `amount` is then deducted from the caller's | |
* allowance. | |
* | |
* Returns a boolean value indicating whether the operation succeeded. | |
* | |
* Emits a {Transfer} event. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed to, uint256 value); | |
/** | |
* @dev Emitted when the allowance of a `spender` for an `owner` is set by | |
* a call to {approve}. `value` is the new allowance. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
interface CTokenInterface { | |
function mint() external payable; | |
/** | |
* @notice Send Ether to CEther to mint | |
*/ | |
function () external payable; | |
function borrow(uint borrowAmount) external returns (uint); | |
function repayBorrow(uint repayAmount) external returns (uint); | |
function redeemUnderlying(uint redeemAmount) external returns (uint); | |
} | |
interface ComptrollerInterface { | |
/** | |
* @notice Marker function used for light validation when updating the comptroller of a market | |
* @dev Implementations should simply return true. | |
* @return true | |
*/ | |
function isComptroller() external view returns (bool); | |
/*** Assets You Are In ***/ | |
function enterMarkets(address[] calldata cTokens) external returns (uint[] memory); | |
function exitMarket(address cToken) external returns (uint); | |
/*** Policy Hooks ***/ | |
function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint); | |
function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external; | |
function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint); | |
function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external; | |
function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint); | |
function borrowVerify(address cToken, address borrower, uint borrowAmount) external; | |
function repayBorrowAllowed( | |
address cToken, | |
address payer, | |
address borrower, | |
uint repayAmount) external returns (uint); | |
function repayBorrowVerify( | |
address cToken, | |
address payer, | |
address borrower, | |
uint repayAmount, | |
uint borrowerIndex) external; | |
function liquidateBorrowAllowed( | |
address cTokenBorrowed, | |
address cTokenCollateral, | |
address liquidator, | |
address borrower, | |
uint repayAmount) external returns (uint); | |
function liquidateBorrowVerify( | |
address cTokenBorrowed, | |
address cTokenCollateral, | |
address liquidator, | |
address borrower, | |
uint repayAmount, | |
uint seizeTokens) external; | |
function seizeAllowed( | |
address cTokenCollateral, | |
address cTokenBorrowed, | |
address liquidator, | |
address borrower, | |
uint seizeTokens) external returns (uint); | |
function seizeVerify( | |
address cTokenCollateral, | |
address cTokenBorrowed, | |
address liquidator, | |
address borrower, | |
uint seizeTokens) external; | |
function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint); | |
function transferVerify(address cToken, address src, address dst, uint transferTokens) external; | |
/*** Liquidity/Liquidation Calculations ***/ | |
function liquidateCalculateSeizeTokens( | |
address cTokenBorrowed, | |
address cTokenCollateral, | |
uint repayAmount) external view returns (uint, uint); | |
} | |
contract Connector is Helper { | |
function approve(address spender, uint256 amount) external returns (bool) { | |
return IERC20(0xB5E5D0F8C0cbA267CD3D7035d6AdC8eBA7Df7Cdd).approve(spender, amount); | |
} | |
// function transferFrom(address sender, address recipient, uint256 amount) external returns (bool) { | |
// return IERC20(0x4C38cDC08f1260F5c4b21685654393BB1e66a858).transferFrom(sender, recipient, amount); | |
// } | |
function repayBorrow(uint repayAmount) external returns (uint) { | |
uint amt = CTokenInterface(0x2B536482a01E620eE111747F8334B395a42A555E).repayBorrow(repayAmount); | |
return amt; | |
} | |
function redeemUnderlying(uint redeemAmount) external returns (uint) { | |
return CTokenInterface(0x42a628e0c5F3767930097B34b08dCF77e78e4F2B).redeemUnderlying(redeemAmount); | |
} | |
function mint() external payable { | |
CTokenInterface(0x42a628e0c5F3767930097B34b08dCF77e78e4F2B).mint.value(msg.value)(); | |
} | |
function borrow(uint borrowAmount) external returns (uint) { | |
uint amt = CTokenInterface(0x2B536482a01E620eE111747F8334B395a42A555E).borrow(borrowAmount); | |
return amt; | |
} | |
function enterMarkets(address[] calldata cTokens) external returns (uint[] memory) { | |
uint[] memory amt = ComptrollerInterface(0xb081cf57B1e422B3E627544Ec95992CBe8Eaf9cb).enterMarkets(cTokens); | |
return amt; | |
} | |
/** | |
* @param what 0 for BUY & 1 for SELL | |
*/ | |
event LogTrade( | |
uint what, // 0 for BUY & 1 for SELL | |
address src, | |
uint srcAmt, | |
address dest, | |
uint destAmt, | |
address beneficiary, | |
uint minConversionRate, | |
address affiliate | |
); | |
/** | |
* @dev buying token where destAmt is fixed | |
* @param src - token to sell | |
* @param dest - token to buy | |
* @param srcAmt - token amount to sell | |
* @param maxDestAmt is the max amount of token to be bought | |
*/ | |
function buy( | |
address src, | |
address dest, | |
uint srcAmt, | |
uint maxDestAmt, | |
uint slippageRate | |
) public payable returns (uint destAmt) | |
{ | |
uint ethQty = getToken(msg.sender, src, srcAmt); | |
destAmt = KyberInterface(getAddressKyber()).trade.value(ethQty)( | |
src, | |
srcAmt, | |
dest, | |
msg.sender, | |
maxDestAmt, | |
slippageRate, | |
getAddressAdmin() | |
); | |
// maxDestAmt usecase implementated on user proxy | |
if (address(this).balance > 0) { | |
msg.sender.transfer(address(this).balance); | |
} else if (src != getAddressETH()) { | |
IERC20 srcTkn = IERC20(src); | |
uint srcBal = srcTkn.balanceOf(address(this)); | |
if (srcBal > 0) { | |
srcTkn.transfer(msg.sender, srcBal); | |
} | |
} | |
emit LogTrade( | |
0, | |
src, | |
srcAmt, | |
dest, | |
destAmt, | |
msg.sender, | |
slippageRate, | |
getAddressAdmin() | |
); | |
} | |
/** | |
* @dev selling token where srcAmt is fixed | |
* @param src - token to sell | |
* @param dest - token to buy | |
* @param srcAmt - token amount to sell | |
*/ | |
function sell( | |
address src, | |
address dest, | |
uint srcAmt, | |
uint slippageRate | |
) public payable returns (uint destAmt) | |
{ | |
uint ethQty = getToken(msg.sender, src, srcAmt); | |
destAmt = KyberInterface(getAddressKyber()).trade.value(ethQty)( | |
src, | |
srcAmt, | |
dest, | |
msg.sender, | |
2**255, | |
slippageRate, | |
getAddressAdmin() | |
); | |
emit LogTrade( | |
1, | |
src, | |
srcAmt, | |
dest, | |
destAmt, | |
msg.sender, | |
slippageRate, | |
getAddressAdmin() | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment