added mkr swap and fixed few bugs in migrate.

This commit is contained in:
Thrilok kumar 2019-10-22 04:25:08 +05:30
parent 73e47ea28e
commit 8dffe62a18

View File

@ -46,6 +46,11 @@ interface UniswapExchange {
uint256 deadline,
address tokenAddr
) external returns (uint256 tokensSold);
function ethToTokenSwapOutput(uint256 tokensBought, uint256 deadline) external payable returns (uint256 ethSold);
}
interface UniswapFactoryInterface {
function getExchange(address token) external view returns (address exchange);
}
interface MCDInterface {
@ -58,6 +63,16 @@ interface PoolInterface {
function paybackToken(address[] calldata ctknAddr, bool isCompound) external payable;
}
interface OtcInterface {
function getPayAmount(address, address, uint) external view returns (uint);
function buyAllAmount(
address,
uint,
address,
uint
) external;
}
contract DSMath {
@ -112,6 +127,20 @@ contract Helpers is DSMath {
dai = 0x448a5065aeBB8E423F0896E6c5D525C040f59af3;
}
/**
* @dev get Compound WETH Address
*/
function getWETHAddress() public pure returns (address wethAddr) {
wethAddr = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // main
}
/**
* @dev get Compound OTC Address
*/
function getOtcAddress() public pure returns (address otcAddr) {
otcAddr = 0x39755357759cE0d7f32dC8dC45414CCa409AE24e; // main
}
/**
* @dev get uniswap MKR exchange
*/
@ -126,6 +155,13 @@ contract Helpers is DSMath {
ude = 0x09cabEC1eAd1c0Ba254B09efb3EE13841712bE14;
}
/**
* @dev get uniswap factory
*/
function getUniswapFactory() public pure returns (address addr) {
addr = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
}
/**
* @dev get InstaDApp Liquidity Address
*/
@ -134,10 +170,14 @@ contract Helpers is DSMath {
}
/**
* @dev get CDP bytes by CDP ID
* @dev setting allowance to compound for the "user proxy" if required
*/
function getCDPBytes(uint cdpNum) public pure returns (bytes32 cup) {
cup = bytes32(cdpNum);
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);
}
}
}
@ -149,7 +189,41 @@ contract SCDResolver is Helpers {
cup = TubInterface(getSaiTubAddress()).open();
}
function lock(bytes32 cup, uint jam) public payable {
function wipe(bytes32 cup, uint _wad) internal {
if (_wad > 0) {
TubInterface tub = TubInterface(getSaiTubAddress());
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());
tub.wipe(cup, _wad);
}
}
function free(bytes32 cup, uint jam) internal {
if (jam > 0) {
address tubAddr = getSaiTubAddress();
TubInterface tub = TubInterface(tubAddr);
TokenInterface peth = tub.skr();
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);
// weth.withdraw(freeJam); // No need because we will lock it in small cdp
}
}
function lock(bytes32 cup, uint jam) internal {
if (jam > 0) {
address tubAddr = getSaiTubAddress();
@ -160,7 +234,7 @@ contract SCDResolver is Helpers {
(address lad,,,) = tub.cups(cup);
require(lad == address(this), "cup-not-owned");
weth.deposit.value(jam)();
// weth.deposit.value(msg.value)(); // no need because withdrawn Weth is not convert back
uint ink = rdiv(jam, tub.per());
ink = rmul(ink, tub.per()) <= jam ? ink : ink - 1;
@ -173,73 +247,13 @@ contract SCDResolver is Helpers {
}
}
function free(bytes32 cup, uint jam) public {
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)); // withdraw possible previous stuck WETH as well
weth.withdraw(freeJam);
}
}
function draw(bytes32 cup, uint _wad) public {
function draw(bytes32 cup, uint _wad) internal {
if (_wad > 0) {
TubInterface tub = TubInterface(getSaiTubAddress());
tub.draw(cup, _wad);
}
}
function wipe(bytes32 cup, uint _wad) public {
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();
//Check Thrilok
// 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));
uint daiAmt = add(_wad, daiFeeAmt);
require(dai.transferFrom(msg.sender, address(this), daiAmt), "not-approved-yet");
if (ok && val != 0) {
daiEx.tokenToTokenSwapOutput(
mkrFee,
daiAmt,
uint(999000000000000000000),
uint(1899063809), // 6th March 2030 GMT // no logic
address(mkr)
);
}
tub.wipe(cup, _wad);
}
}
function setAllowance(TokenInterface _token, address _spender) private {
if (_token.allowance(address(this), _spender) != uint(-1)) {
_token.approve(_spender, uint(-1));
@ -249,7 +263,53 @@ contract SCDResolver is Helpers {
}
contract MCDResolver is SCDResolver {
contract MkrResolver is SCDResolver {
function swapToMkrOtc(address tokenAddr, uint govFee) internal {
TokenInterface mkr = TubInterface(getSaiTubAddress()).gov();
uint payAmt = OtcInterface(getOtcAddress()).getPayAmount(tokenAddr, address(mkr), govFee);
if (tokenAddr == getWETHAddress()) {
TokenInterface weth = TokenInterface(getWETHAddress());
weth.deposit.value(payAmt)();
} else {
require(TokenInterface(tokenAddr).transferFrom(msg.sender, address(this), payAmt), "Tranfer-failed");
}
setApproval(tokenAddr, payAmt, getOtcAddress());
OtcInterface(getOtcAddress()).buyAllAmount(
address(mkr),
govFee,
tokenAddr,
payAmt
);
}
function swapToMkrUniswap(address tokenAddr, uint govFee) internal {
UniswapExchange mkrEx = UniswapExchange(getUniswapMKRExchange());
address uniSwapFactoryAddr = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
TokenInterface mkr = TubInterface(getSaiTubAddress()).gov();
if (tokenAddr == getWETHAddress()) {
uint ethNeeded = mkrEx.getEthToTokenOutputPrice(govFee);
mkrEx.ethToTokenSwapOutput.value(ethNeeded)(govFee, uint(1899063809));
} else {
address buyTknExAddr = UniswapFactoryInterface(uniSwapFactoryAddr).getExchange(tokenAddr);
UniswapExchange buyTknEx = UniswapExchange(buyTknExAddr);
uint tknAmt = buyTknEx.getTokenToEthOutputPrice(mkrEx.getEthToTokenOutputPrice(govFee)); //Check thrilok is this correct
require(TokenInterface(tokenAddr).transferFrom(msg.sender, address(this), tknAmt), "not-approved-yet");
setApproval(tokenAddr, tknAmt, buyTknExAddr);
buyTknEx.tokenToTokenSwapOutput(
govFee,
tknAmt,
uint(999000000000000000000),
uint(1899063809), // 6th March 2030 GMT // no logic
address(mkr)
);
}
}
}
contract MCDResolver is MkrResolver {
function swapDaiToSai(
address payable scdMcdMigration, // Migration contract address
uint wad // Amount to swap
@ -268,7 +328,6 @@ contract MCDResolver is SCDResolver {
address payable scdMcdMigration, // Migration contract address
bytes32 cup, // SCD CDP Id to migrate
address payGem // Token address (only if gov fee will be paid with another token)
// uint maxPayAmt // Max amount of payGem to sell for govFee needed (only if gov fee will be paid with another token)
) internal returns (uint cdp)
{
TubInterface tub = TubInterface(getSaiTubAddress());
@ -281,10 +340,8 @@ contract MCDResolver is SCDResolver {
uint govFee = wdiv(tub.rap(cup), uint(val));
if (payGem != address(0)) {
// Swap ETH to WETH => WETH TO MKR
swapToMkrOtc(payGem, govFee);
} else {
// Else get MKR from the user's wallet and transfer to Migration contract
require(tub.gov().transferFrom(msg.sender, address(this), govFee), "transfer-failed");
}
require(tub.gov().transfer(address(scdMcdMigration), govFee), "transfer-failed");
@ -296,6 +353,7 @@ contract MCDResolver is SCDResolver {
contract MigrateResolver is MCDResolver {
event LogMigrate(uint scdCdp, uint toConvert, address payFeeWith, uint mcdCdp);
function migrate(
bytes32 scdCup,
// uint mcdCDP, for merge
@ -307,13 +365,14 @@ contract MigrateResolver is MCDResolver {
TubInterface tub = TubInterface(getSaiTubAddress());
uint _jam = rmul(tub.ink(scdCup), tub.per());
uint _wad = tub.tab(scdCup);
if (toConvert >= 10**18) {
if (toConvert < 10**18) {
uint initialPoolBal = sub(getPoolAddress().balance, 10000000000);
bytes32 splitCup = TubInterface(getSaiTubAddress()).open();
_jam = wmul(_jam, toConvert);
_wad = wmul(_wad, toConvert);
uint[] memory _wadArr = new uint[](1);
_wadArr[0] = _wad;
@ -323,13 +382,21 @@ contract MigrateResolver is MCDResolver {
// Get liquidity assets to payback user wallet borrowed assets
PoolInterface(getPoolAddress()).accessToken(addrArr, _wadArr, false);
(bytes32 val, bool ok) = tub.pep().peek();
if (ok && val != 0) {
// MKR required for wipe = Stability fees accrued in Dai / MKRUSD value
uint mkrFee = wdiv(rmul(_wad, rdiv(tub.rap(scdCup), tub.tab(scdCup))), uint(val));
swapToMkrUniswap(payFeeWith, mkrFee);
}
wipe(scdCup, _wad);
free(scdCup, _jam);
lock(splitCup, _jam);
draw(splitCup, _wad);
require(TokenInterface(getSaiAddress()).transfer(getPoolAddress(), _wad), "Not-enough-amt");
require(TokenInterface(getSaiAddress()).transfer(getPoolAddress(), _wad), "Not-enough-dai");
PoolInterface(getPoolAddress()).paybackToken(addrArr, false);
uint finalPoolBal = getPoolAddress().balance;
@ -339,6 +406,12 @@ contract MigrateResolver is MCDResolver {
} else {
cdp = migrateToMCD(scdMcdMigration, scdCup, payFeeWith);
}
emit LogMigrate(
uint(scdCup),
toConvert,
payFeeWith,
cdp
);
}
}