bridge in process

This commit is contained in:
Samyak Jain 2019-06-19 20:22:24 +05:30
parent fb62a95d9b
commit 6886c863df
3 changed files with 300 additions and 44 deletions

View File

@ -0,0 +1,178 @@
pragma solidity ^0.5.7;
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);
function deposit() external payable;
function withdraw(uint) external;
}
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 (ERC20Interface);
function gov() external view returns (ERC20Interface);
function skr() external view returns (ERC20Interface);
function sai() external view returns (ERC20Interface);
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 PepInterface {
function peek() external returns (bytes32, 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);
}
interface CTokenInterface {
function borrow(uint borrowAmount) external returns (uint);
function transfer(address, uint) external returns (bool);
function transferFrom(address, address, uint) external returns (bool);
}
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 get MakerDAO CDP engine
*/
function getSaiTubAddress() public pure returns (address sai) {
sai = 0x448a5065aeBB8E423F0896E6c5D525C040f59af3;
}
/**
* @dev get Compound Comptroller Address
*/
function getComptrollerAddress() public pure returns (address troller) {
troller = 0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B;
}
/**
* @dev get Compound Comptroller Address
*/
function getDAIAddress() public pure returns (address dai) {
dai = 0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359;
}
/**
* @dev get Compound Comptroller Address
*/
function getCDAIAddress() public pure returns (address cDai) {
cDai = 0xF5DCe57282A584D2746FaF1593d3121Fcac444dC;
}
/**
* @dev get Compound Comptroller Address
*/
function getBridgeAddress() public pure returns (address bridge) {
bridge = ;// <BRIDGE ADDRESS>
}
/**
* @dev setting allowance to compound for the "user proxy" if required
*/
function setApproval(address erc20, uint srcAmt, address to) internal {
ERC20Interface erc20Contract = ERC20Interface(erc20);
uint tokenAllowance = erc20Contract.allowance(address(this), to);
if (srcAmt > tokenAllowance) {
erc20Contract.approve(to, 2**255);
}
}
}
contract MakerHelper is Helper {
/**
* @dev transfer CDP ownership
*/
function give(uint cdpNum, address nextOwner) internal {
TubInterface(getSaiTubAddress()).give(bytes32(cdpNum), nextOwner);
}
}
contract CompoundHelper is MakerHelper {
function enterMarket(address cErc20) internal {
ComptrollerInterface troller = ComptrollerInterface(getComptrollerAddress());
address[] memory markets = troller.getAssetsIn(address(this));
bool isEntered = false;
for (uint i = 0; i < markets.length; i++) {
if (markets[i] == cErc20) {
isEntered = true;
}
}
if (!isEntered) {
address[] memory toEnter = new address[](1);
toEnter[0] = cErc20;
troller.enterMarkets(toEnter);
}
}
/**
* @dev borrow ETH/ERC20
*/
function borrowDai(uint tokenAmt) internal {
enterMarket(getCDAIAddress());
CTokenInterface cDaiContract = CTokenInterface(getCDAIAddress());
require(cDaiContract.borrow(tokenAmt) == 0, "got collateral?");
cDaiContract.transfer(getBridgeAddress());
}
}

View File

@ -168,7 +168,7 @@ contract Helper is DSMath {
eth = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
}
/**
/**
* @dev get MakerDAO CDP engine
*/
function getSaiTubAddress() public pure returns (address sai) {

View File

@ -34,17 +34,6 @@ interface PepInterface {
function peek() external returns (bytes32, bool);
}
interface CTokenInterface {
function mint(uint mintAmount) external returns (uint); // For ERC20
function redeem(uint redeemTokens) external returns (uint);
function redeemUnderlying(uint redeemAmount) external returns (uint);
function exchangeRateCurrent() external returns (uint);
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 ERC20Interface {
function allowance(address, address) external view returns (uint);
function balanceOf(address) external view returns (uint);
@ -67,6 +56,15 @@ interface UniswapExchange {
) external returns (uint256 tokensSold);
}
interface CTokenInterface {
function redeem(uint redeemTokens) external returns (uint);
function redeemUnderlying(uint redeemAmount) external returns (uint);
function exchangeRateCurrent() external returns (uint);
function transfer(address, uint) external returns (bool);
function transferFrom(address, address, uint) external returns (bool);
function balanceOf(address) external view returns (uint);
}
interface CETHInterface {
function mint() external payable; // For ETH
function transfer(address, uint) external returns (bool);
@ -74,6 +72,7 @@ interface CETHInterface {
interface CDAIInterface {
function mint(uint mintAmount) external returns (uint); // For ERC20
function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);
}
@ -155,7 +154,20 @@ contract MakerResolver is Helper {
event LogWipe(uint cdpNum, uint daiAmt, uint mkrFee, uint daiFee, address owner);
event LogShut(uint cdpNum);
function wipe(uint cdpNum, uint _wad) public returns (uint daiAmt) {
function open() internal returns (uint) {
bytes32 cup = TubInterface(sai).open();
emit LogOpen(uint(cup), address(this));
return uint(cup);
}
/**
* @dev transfer CDP ownership
*/
function give(uint cdpNum, address nextOwner) internal {
TubInterface(sai).give(bytes32(cdpNum), nextOwner);
}
function wipe(uint cdpNum, uint _wad) internal returns (uint daiAmt) {
if (_wad > 0) {
TubInterface tub = TubInterface(sai);
UniswapExchange daiEx = UniswapExchange(ude);
@ -204,7 +216,7 @@ contract MakerResolver is Helper {
}
}
function free(uint cdpNum, uint jam) public {
function free(uint cdpNum, uint jam) internal {
if (jam > 0) {
bytes32 cup = bytes32(cdpNum);
address tubAddr = sai;
@ -234,11 +246,60 @@ contract MakerResolver is Helper {
}
}
function wipeAndFree(uint cdpNum, uint jam, uint _wad) internal {
wipe(cdpNum, _wad);
function lock(uint cdpNum, uint ethAmt) internal {
if (msg.value > 0) {
bytes32 cup = bytes32(cdpNum);
address tubAddr = sai;
TubInterface tub = TubInterface(tubAddr);
ERC20Interface weth = tub.gem();
// ERC20Interface peth = tub.skr();
(address lad,,,) = tub.cups(cup);
require(lad == address(this), "cup-not-owned");
weth.deposit.value(ethAmt)();
uint ink = rdiv(ethAmt, tub.per());
ink = rmul(ink, tub.per()) <= ethAmt ? ink : ink - 1;
// setAllowance(weth, tubAddr);
tub.join(ink);
// setAllowance(peth, tubAddr);
tub.lock(cup, ink);
emit LogLock(
cdpNum,
ethAmt,
ink,
address(this)
);
}
}
function draw(uint cdpNum, uint _wad) internal {
bytes32 cup = bytes32(cdpNum);
if (_wad > 0) {
TubInterface tub = TubInterface(sai);
tub.draw(cup, _wad);
// tub.sai().transfer(msg.sender, _wad);
emit LogDraw(cdpNum, _wad, address(this));
}
}
function wipeAndFree(uint cdpNum, uint jam, uint _wad) internal returns (uint daiAmt) {
daiAmt = wipe(cdpNum, _wad);
free(cdpNum, jam);
}
function lockAndDraw(uint cdpNum, uint jam, uint _wad) internal {
lock(cdpNum, jam);
draw(cdpNum, _wad);
}
}
@ -249,40 +310,14 @@ contract CompoundResolver is MakerResolver {
event LogBorrow(address erc20, address cErc20, uint tokenAmt, address owner);
event LogRepay(address erc20, address cErc20, uint tokenAmt, address owner);
/**
* @dev Deposit ETH/ERC20 and mint Compound Tokens
*/
function mintCToken(address erc20, address cErc20, uint tokenAmt) external payable {
enterMarket(cErc20);
if (erc20 == getAddressETH()) {
CETHInterface cToken = CETHInterface(cErc20);
cToken.mint.value(msg.value)();
} else {
ERC20Interface token = ERC20Interface(erc20);
uint toDeposit = token.balanceOf(msg.sender);
if (toDeposit > tokenAmt) {
toDeposit = tokenAmt;
}
token.transferFrom(msg.sender, address(this), toDeposit);
CERC20Interface cToken = CERC20Interface(cErc20);
setApproval(erc20, toDeposit, cErc20);
assert(cToken.mint(toDeposit) == 0);
}
emit LogMint(
erc20,
cErc20,
tokenAmt,
msg.sender
);
}
/**
* @dev Deposit ETH/ERC20 and mint Compound Tokens
*/
function mintCETH(uint tokenAmt) internal {
CETHInterface cToken = CETHInterface(cEth);
cToken.mint.value(tokenAmt)();
cToken.transfer(msg.sender, tokenAmt);
uint cEthToReturn = wdiv(tokenAmt, CTokenInterface(cEth).exchangeRateCurrent());
cToken.transfer(msg.sender, cEthToReturn);
emit LogMint(
ethAddr,
cEth,
@ -310,14 +345,57 @@ contract CompoundResolver is MakerResolver {
);
}
/**
* @dev Redeem ETH/ERC20 and mint Compound Tokens
* @param tokenAmt Amount of token To Redeem
*/
function redeemUnderlying(address cErc20, uint tokenAmt) internal {
CTokenInterface cToken = CTokenInterface(cErc20);
// setApproval(cErc20, 10**50, cErc20);
uint toBurn = cToken.balanceOf(address(this));
uint tokenToReturn = wmul(toBurn, cToken.exchangeRateCurrent());
tokenToReturn = tokenToReturn > tokenAmt ? tokenAmt : tokenToReturn;
require(cToken.redeemUnderlying(tokenToReturn) == 0, "something went wrong");
}
function takeCETH(uint ethAmt) internal {
CTokenInterface cToken = CTokenInterface(cEth);
uint cTokenAmt = wdiv(ethAmt, cToken.exchangeRateCurrent());
uint cEthBal = cToken.balanceOf(msg.sender);
cTokenAmt = cEthBal > cTokenAmt ? cTokenAmt : cTokenAmt - 1;
require(ERC20Interface(cEth).transferFrom(msg.sender, address(this), cTokenAmt), "Contract Approved?");
}
}
contract Bridge is CompoundResolver {
function payUsersDebt(uint daiDebt) internal {
redeemUnderlying(cDai, daiDebt);
// setApproval(dai, daiDebt, cDai);
require(CDAIInterface(cDai).repayBorrowBehalf(msg.sender, daiDebt) == 0, "Enough DAI?");
}
function takeDebtBack(uint daiDebt) external {
require(ERC20Interface(daiAddr).transferFrom(msg.sender, address(this),daiDebt), "Contract Approved?");
mintCDAI(daiDebt);
}
function makerToCompound(uint cdpId, uint ethCol, uint daiDebt) public payable isUserWallet returns (uint daiAmt) {
daiAmt = wipeAndFree(cdpId, ethCol, daiDebt);
mintCETH(ethCol);
give(cdpId, msg.sender);
}
function compoundToMaker(uint cdpId, uint ethCol, uint daiDebt) public payable isUserWallet returns (uint daiAmt) {
payUsersDebt(daiDebt);
takeCETH(ethCol);
redeemUnderlying(cEth, ethCol);
uint cdpNum = cdpId > 0 ? cdpId : open();
lockAndDraw(cdpNum, ethCol, daiDebt);
mintCDAI(daiDebt);
give(cdpNum, msg.sender);
}
}