diff --git a/contracts/ProxyLogics/InstaBridge.sol b/contracts/ProxyLogics/InstaBridge.sol new file mode 100644 index 0000000..dc64a12 --- /dev/null +++ b/contracts/ProxyLogics/InstaBridge.sol @@ -0,0 +1,330 @@ +pragma solidity ^0.5.7; + +interface TubInterface { + function open() external returns (bytes32); + function join(uint) external; + function exit(uint) external; + function lock(bytes32, uint) external; + function free(bytes32, uint) external; + function draw(bytes32, uint) external; + function wipe(bytes32, uint) external; + function give(bytes32, address) external; + function shut(bytes32) external; + function cups(bytes32) external view returns (address, uint, uint, uint); + function gem() external view returns (TokenInterface); + function gov() external view returns (TokenInterface); + function skr() external view returns (TokenInterface); + function sai() external view returns (TokenInterface); + function ink(bytes32) external view returns (uint); + function tab(bytes32) external returns (uint); + function rap(bytes32) external returns (uint); + function per() external view returns (uint); + function pep() external view returns (PepInterface); +} + +interface TokenInterface { + function allowance(address, address) external view returns (uint); + function balanceOf(address) external view returns (uint); + function approve(address, uint) external; + function transfer(address, uint) external returns (bool); + function transferFrom(address, address, uint) external returns (bool); + function deposit() external payable; + function withdraw(uint) external; +} + +interface PepInterface { + function peek() external returns (bytes32, bool); +} + +interface UniswapExchange { + function getEthToTokenOutputPrice(uint256 tokensBought) external view returns (uint256 ethSold); + function getTokenToEthOutputPrice(uint256 ethBought) external view returns (uint256 tokensSold); + function tokenToTokenSwapOutput( + uint256 tokensBought, + uint256 maxTokensSold, + uint256 maxEthSold, + uint256 deadline, + address tokenAddr + ) external returns (uint256 tokensSold); +} + +interface BridgeInterface { + function transferDAI(uint) external; +} + +interface CTokenInterface { + function redeem(uint redeemTokens) external returns (uint); + function redeemUnderlying(uint redeemAmount) external returns (uint); + function borrow(uint borrowAmount) external returns (uint); + function liquidateBorrow(address borrower, uint repayAmount, address cTokenCollateral) external returns (uint); + function liquidateBorrow(address borrower, address cTokenCollateral) external payable; + function exchangeRateCurrent() external returns (uint); + function getCash() external view returns (uint); + function totalBorrowsCurrent() external returns (uint); + function borrowRatePerBlock() external view returns (uint); + function supplyRatePerBlock() external view returns (uint); + function totalReserves() external view returns (uint); + function reserveFactorMantissa() external view returns (uint); + + function totalSupply() external view returns (uint256); + function balanceOf(address owner) external view returns (uint256 balance); + function allowance(address, address) external view returns (uint); + function approve(address, uint) external; + function transfer(address, uint) external returns (bool); + function transferFrom(address, address, uint) external returns (bool); +} + +interface CERC20Interface { + function mint(uint mintAmount) external returns (uint); // For ERC20 + function repayBorrow(uint repayAmount) external returns (uint); // For ERC20 + function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint); // For ERC20 + function borrowBalanceCurrent(address account) external returns (uint); +} + +interface CETHInterface { + function mint() external payable; // For ETH + function repayBorrow() external payable; // For ETH + function repayBorrowBehalf(address borrower) external payable; // For ETH + function borrowBalanceCurrent(address account) external returns (uint); +} + +interface ERC20Interface { + function allowance(address, address) external view returns (uint); + function balanceOf(address) external view returns (uint); + function approve(address, uint) external; + function transfer(address, uint) external returns (bool); + function transferFrom(address, address, uint) external returns (bool); +} + +interface ComptrollerInterface { + function enterMarkets(address[] calldata cTokens) external returns (uint[] memory); + function exitMarket(address cTokenAddress) external returns (uint); + function getAssetsIn(address account) external view returns (address[] memory); + function getAccountLiquidity(address account) external view returns (uint, uint, uint); +} + + +contract DSMath { + + function add(uint x, uint y) internal pure returns (uint z) { + require((z = x + y) >= x, "math-not-safe"); + } + + function mul(uint x, uint y) internal pure returns (uint z) { + require(y == 0 || (z = x * y) / y == x, "math-not-safe"); + } + + uint constant WAD = 10 ** 18; + uint constant RAY = 10 ** 27; + + function rmul(uint x, uint y) internal pure returns (uint z) { + z = add(mul(x, y), RAY / 2) / RAY; + } + + function rdiv(uint x, uint y) internal pure returns (uint z) { + z = add(mul(x, RAY), y / 2) / y; + } + + function wmul(uint x, uint y) internal pure returns (uint z) { + z = add(mul(x, y), WAD / 2) / WAD; + } + + function wdiv(uint x, uint y) internal pure returns (uint z) { + z = add(mul(x, WAD), y / 2) / y; + } + +} + + +contract Helper is DSMath { + + /** + * @dev setting allowance to compound for the "user proxy" if required + */ + function setApproval(address erc20, uint srcAmt, address to) internal { + TokenInterface erc20Contract = TokenInterface(erc20); + uint tokenAllowance = erc20Contract.allowance(address(this), to); + if (srcAmt > tokenAllowance) { + erc20Contract.approve(to, 2**255); + } + } + + /** + * @dev get ethereum address for trade + */ + function getAddressETH() public pure returns (address eth) { + eth = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + } + + /** + * @dev get MakerDAO CDP engine + */ + function getSaiTubAddress() public pure returns (address sai) { + sai = 0x448a5065aeBB8E423F0896E6c5D525C040f59af3; + } + + /** + * @dev get uniswap MKR exchange + */ + function getUniswapMKRExchange() public pure returns (address ume) { + ume = 0x2C4Bd064b998838076fa341A83d007FC2FA50957; + } + + /** + * @dev get uniswap DAI exchange + */ + function getUniswapDAIExchange() public pure returns (address ude) { + ude = 0x09cabEC1eAd1c0Ba254B09efb3EE13841712bE14; + } + + /** + * @dev get uniswap DAI exchange + */ + function getBridgeAddress() public pure returns (address bridge) { + // bridge = ; + } + + /** + * @dev get CDP bytes by CDP ID + */ + function getCDPBytes(uint cdpNum) public pure returns (bytes32 cup) { + cup = bytes32(cdpNum); + } + +} + + +contract MakerHelper is Helper { + + event LogFree(uint cdpNum, uint amtETH, uint amtPETH, address owner); + event LogWipe(uint cdpNum, uint daiAmt, uint mkrFee, uint daiFee, address owner); + event LogShut(uint cdpNum); + + function setAllowance(TokenInterface _token, address _spender) private { + if (_token.allowance(address(this), _spender) != uint(-1)) { + _token.approve(_spender, uint(-1)); + } + } + + function getCDPStats(bytes32 cup) internal view returns (uint ethCol, uint daiDebt) { + TubInterface tub = TubInterface(getSaiTubAddress()); + (, uint pethCol, uint debt,) = tub.cups(cup); + ethCol = rmul(pethCol, tub.per()); // get ETH col from PETH col + daiDebt = debt; + } + + function free(bytes32 cup, uint jam) internal { + if (jam > 0) { + address tubAddr = getSaiTubAddress(); + + TubInterface tub = TubInterface(tubAddr); + TokenInterface peth = tub.skr(); + TokenInterface weth = tub.gem(); + + uint ink = rdiv(jam, tub.per()); + ink = rmul(ink, tub.per()) <= jam ? ink : ink - 1; + tub.free(cup, ink); + + setAllowance(peth, tubAddr); + + tub.exit(ink); + uint freeJam = weth.balanceOf(address(this)); // convert previous WETH into ETH as well + weth.withdraw(freeJam); + + emit LogFree( + uint(cup), + freeJam, + ink, + address(this) + ); + } + } + + function wipe(bytes32 cup, uint _wad) internal returns (uint daiAmt) { + if (_wad > 0) { + TubInterface tub = TubInterface(getSaiTubAddress()); + UniswapExchange daiEx = UniswapExchange(getUniswapDAIExchange()); + UniswapExchange mkrEx = UniswapExchange(getUniswapMKRExchange()); + TokenInterface dai = tub.sai(); + TokenInterface mkr = tub.gov(); + + (address lad,,,) = tub.cups(cup); + require(lad == address(this), "cup-not-owned"); + + setAllowance(dai, getSaiTubAddress()); + setAllowance(mkr, getSaiTubAddress()); + setAllowance(dai, getUniswapDAIExchange()); + + (bytes32 val, bool ok) = tub.pep().peek(); + + // MKR required for wipe = Stability fees accrued in Dai / MKRUSD value + uint mkrFee = wdiv(rmul(_wad, rdiv(tub.rap(cup), tub.tab(cup))), uint(val)); + + uint daiFeeAmt = daiEx.getTokenToEthOutputPrice(mkrEx.getEthToTokenOutputPrice(mkrFee)); + daiAmt = add(_wad, daiFeeAmt); + BridgeInterface(getBridgeAddress()).transferDAI(daiAmt); + + if (ok && val != 0) { + daiEx.tokenToTokenSwapOutput( + mkrFee, + daiAmt, + uint(999000000000000000000), + uint(1899063809), // 6th March 2030 GMT // no logic + address(mkr) + ); + } + + tub.wipe(cup, _wad); + + emit LogWipe( + uint(cup), + daiAmt, + mkrFee, + daiFeeAmt, + address(this) + ); + + } + } + + function wipeAndFree(bytes32 cup, uint jam, uint _wad) internal returns (uint daiAmt) { + daiAmt = wipe(cup, _wad); + free(cup, jam); + } + + /** + * @dev close CDP + */ + function shut(bytes32 cup) internal returns (uint daiAmt) { + TubInterface tub = TubInterface(getSaiTubAddress()); + daiAmt = wipeAndFree(cup, rmul(tub.ink(cup), tub.per()), tub.tab(cup)); + tub.shut(cup); + emit LogShut(uint(cup)); // fetch remaining data from WIPE & FREE events + } + +} + + +contract CompoundHelper is MakerHelper { + +} + + +contract Bridge is CompoundHelper { + + function makerToCompound(uint cdpId, uint toConvert) public { // toConvert ranges from 0 to 1 and has (18 decimals) + bytes32 cup = bytes32(cdpId); + (uint ethCol, uint daiDebt) = getCDPStats(cup); + uint ethFree = ethCol; + uint daiAmt = daiDebt; + if (toConvert < 10**18) { + uint wipeAmt = wmul(daiDebt, toConvert); + ethFree = wmul(ethCol, toConvert); + daiAmt = wipe(cup, wipeAmt); + free(cup, ethFree); + } else { + daiAmt = shut(cup); + } + } + +} \ No newline at end of file