dsa-connectors/contracts/mainnet/connectors/reflexer/main.sol

427 lines
15 KiB
Solidity
Raw Normal View History

2021-03-29 09:57:54 +00:00
pragma solidity ^0.7.0;
/**
* @title Reflexer.
* @dev Collateralized Borrowing.
*/
2021-03-29 09:57:54 +00:00
import { TokenInterface } from "../../common/interfaces.sol";
import { Helpers } from "./helpers.sol";
import { Events } from "./events.sol";
2021-03-29 10:34:18 +00:00
import { SafeEngineLike, TokenJoinInterface } from "./interface.sol";
2021-03-29 09:57:54 +00:00
2021-03-29 15:20:34 +00:00
abstract contract GebResolver is Helpers, Events {
2021-03-29 09:57:54 +00:00
/**
2021-03-29 15:20:34 +00:00
* @dev Open Safe
* @notice Open a Reflexer Safe.
2021-03-29 09:57:54 +00:00
* @param colType Type of Collateral.(eg: 'ETH-A')
*/
function open(string calldata colType) external payable returns (string memory _eventName, bytes memory _eventParam) {
2021-03-29 15:20:34 +00:00
bytes32 collateralType = stringToBytes32(colType);
2021-03-30 10:52:29 +00:00
require(getCollateralJoinAddress(collateralType) != address(0), "wrong-col-type");
2021-03-29 15:20:34 +00:00
uint256 safe = managerContract.openSAFE(collateralType, address(this));
2021-03-29 09:57:54 +00:00
_eventName = "LogOpen(uint256,bytes32)";
2021-03-29 15:20:34 +00:00
_eventParam = abi.encode(safe, collateralType);
2021-03-29 09:57:54 +00:00
}
/**
2021-03-29 15:20:34 +00:00
* @dev Close Safe
* @notice Close a Reflexer Safe.
2021-03-29 15:20:34 +00:00
* @param safe Safe ID to close.
2021-03-29 09:57:54 +00:00
*/
2021-03-29 15:20:34 +00:00
function close(uint256 safe) external payable returns (string memory _eventName, bytes memory _eventParam) {
uint _safe = getSafe(safe);
(bytes32 collateralType, address handler) = getSafeData(_safe);
(uint collateral, uint debt) = SafeEngineLike(managerContract.safeEngine()).safes(collateralType, handler);
2021-03-29 09:57:54 +00:00
2021-03-29 15:20:34 +00:00
require(collateral == 0 && debt == 0, "safe-has-assets");
require(managerContract.ownsSAFE(_safe) == address(this), "not-owner");
2021-03-29 09:57:54 +00:00
2021-03-29 15:20:34 +00:00
managerContract.transferSAFEOwnership(_safe, giveAddr);
2021-03-29 09:57:54 +00:00
_eventName = "LogClose(uint256,bytes32)";
2021-03-29 15:20:34 +00:00
_eventParam = abi.encode(_safe, collateralType);
2021-03-29 09:57:54 +00:00
}
/**
* @dev Deposit ETH/ERC20_Token Collateral.
* @notice Deposit collateral to a Reflexer safe
2021-03-29 15:20:34 +00:00
* @param safe Safe ID.
2021-03-29 09:57:54 +00:00
* @param amt token amount to deposit.
* @param getId Get token amount at this ID from `InstaMemory` Contract.
* @param setId Set token amount at this ID in `InstaMemory` Contract.
*/
function deposit(
2021-03-29 15:20:34 +00:00
uint256 safe,
2021-03-29 09:57:54 +00:00
uint256 amt,
uint256 getId,
uint256 setId
) external payable returns (string memory _eventName, bytes memory _eventParam) {
uint _amt = getUint(getId, amt);
2021-03-29 15:20:34 +00:00
uint _safe = getSafe(safe);
(bytes32 collateralType, address handler) = getSafeData(_safe);
2021-03-29 09:57:54 +00:00
2021-03-30 10:52:29 +00:00
address colAddr = getCollateralJoinAddress(collateralType);
2021-03-29 09:57:54 +00:00
TokenJoinInterface tokenJoinContract = TokenJoinInterface(colAddr);
2021-03-29 10:34:18 +00:00
TokenInterface tokenContract = tokenJoinContract.collateral();
2021-03-29 09:57:54 +00:00
if (isEth(address(tokenContract))) {
_amt = _amt == uint(-1) ? address(this).balance : _amt;
tokenContract.deposit{value: _amt}();
} else {
_amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt;
}
approve(tokenContract, address(colAddr), _amt);
2021-03-29 09:57:54 +00:00
tokenJoinContract.join(address(this), _amt);
2021-03-29 10:34:18 +00:00
SafeEngineLike(managerContract.safeEngine()).modifySAFECollateralization(
2021-03-29 15:20:34 +00:00
collateralType,
handler,
2021-03-29 09:57:54 +00:00
address(this),
address(this),
2021-03-29 10:34:18 +00:00
toInt(convertTo18(tokenJoinContract.decimals(), _amt)),
2021-03-29 09:57:54 +00:00
0
);
setUint(setId, _amt);
_eventName = "LogDeposit(uint256,bytes32,uint256,uint256,uint256)";
2021-03-29 15:20:34 +00:00
_eventParam = abi.encode(_safe, collateralType, _amt, getId, setId);
2021-03-29 09:57:54 +00:00
}
/**
* @dev Withdraw ETH/ERC20_Token Collateral.
* @notice Withdraw collateral from a Reflexer Safe
2021-03-29 15:20:34 +00:00
* @param safe Safe ID.
2021-03-29 09:57:54 +00:00
* @param amt token amount to withdraw.
* @param getId Get token amount at this ID from `InstaMemory` Contract.
* @param setId Set token amount at this ID in `InstaMemory` Contract.
*/
function withdraw(
2021-03-29 15:20:34 +00:00
uint256 safe,
2021-03-29 09:57:54 +00:00
uint256 amt,
uint256 getId,
uint256 setId
) external payable returns (string memory _eventName, bytes memory _eventParam) {
uint _amt = getUint(getId, amt);
2021-03-29 15:20:34 +00:00
uint _safe = getSafe(safe);
(bytes32 collateralType, address handler) = getSafeData(_safe);
2021-03-29 09:57:54 +00:00
2021-03-30 10:52:29 +00:00
address colAddr = getCollateralJoinAddress(collateralType);
2021-03-29 09:57:54 +00:00
TokenJoinInterface tokenJoinContract = TokenJoinInterface(colAddr);
uint _amt18;
if (_amt == uint(-1)) {
2021-03-29 15:20:34 +00:00
(_amt18,) = SafeEngineLike(managerContract.safeEngine()).safes(collateralType, handler);
2021-03-29 10:34:18 +00:00
_amt = convert18ToDec(tokenJoinContract.decimals(), _amt18);
2021-03-29 09:57:54 +00:00
} else {
2021-03-29 10:34:18 +00:00
_amt18 = convertTo18(tokenJoinContract.decimals(), _amt);
2021-03-29 09:57:54 +00:00
}
2021-03-29 10:34:18 +00:00
managerContract.modifySAFECollateralization(
2021-03-29 15:20:34 +00:00
_safe,
2021-03-29 09:57:54 +00:00
-toInt(_amt18),
0
);
2021-03-29 10:34:18 +00:00
managerContract.transferCollateral(
2021-03-29 15:20:34 +00:00
_safe,
2021-03-29 09:57:54 +00:00
address(this),
_amt18
);
2021-03-29 10:34:18 +00:00
TokenInterface tokenContract = tokenJoinContract.collateral();
2021-03-29 09:57:54 +00:00
if (isEth(address(tokenContract))) {
tokenJoinContract.exit(address(this), _amt);
tokenContract.withdraw(_amt);
} else {
tokenJoinContract.exit(address(this), _amt);
}
setUint(setId, _amt);
_eventName = "LogWithdraw(uint256,bytes32,uint256,uint256,uint256)";
2021-03-29 15:20:34 +00:00
_eventParam = abi.encode(_safe, collateralType, _amt, getId, setId);
2021-03-29 09:57:54 +00:00
}
/**
2021-03-29 15:20:34 +00:00
* @dev Borrow Coin.
* @notice Borrow Coin using a Reflexer safe
2021-03-29 15:20:34 +00:00
* @param safe Safe ID.
2021-03-29 09:57:54 +00:00
* @param amt token amount to borrow.
* @param getId Get token amount at this ID from `InstaMemory` Contract.
* @param setId Set token amount at this ID in `InstaMemory` Contract.
*/
function borrow(
2021-03-29 15:20:34 +00:00
uint256 safe,
2021-03-29 09:57:54 +00:00
uint256 amt,
uint256 getId,
uint256 setId
) external payable returns (string memory _eventName, bytes memory _eventParam) {
uint _amt = getUint(getId, amt);
2021-03-29 15:20:34 +00:00
uint _safe = getSafe(safe);
(bytes32 collateralType, address handler) = getSafeData(_safe);
2021-03-29 09:57:54 +00:00
2021-03-29 15:20:34 +00:00
SafeEngineLike safeEngineContract = SafeEngineLike(managerContract.safeEngine());
2021-03-29 09:57:54 +00:00
2021-03-29 10:34:18 +00:00
managerContract.modifySAFECollateralization(
2021-03-29 15:20:34 +00:00
_safe,
2021-03-29 09:57:54 +00:00
0,
_getBorrowAmt(
2021-03-29 15:20:34 +00:00
address(safeEngineContract),
handler,
collateralType,
2021-03-29 09:57:54 +00:00
_amt
)
);
2021-03-29 10:34:18 +00:00
managerContract.transferInternalCoins(
2021-03-29 15:20:34 +00:00
_safe,
2021-03-29 09:57:54 +00:00
address(this),
toRad(_amt)
);
2021-03-29 15:20:34 +00:00
if (safeEngineContract.safeRights(address(this), address(coinJoinContract)) == 0) {
safeEngineContract.approveSAFEModification(address(coinJoinContract));
2021-03-29 09:57:54 +00:00
}
2021-03-29 15:20:34 +00:00
coinJoinContract.exit(address(this), _amt);
2021-03-29 09:57:54 +00:00
setUint(setId, _amt);
_eventName = "LogBorrow(uint256,bytes32,uint256,uint256,uint256)";
2021-03-29 15:20:34 +00:00
_eventParam = abi.encode(_safe, collateralType, _amt, getId, setId);
2021-03-29 09:57:54 +00:00
}
/**
2021-03-29 15:20:34 +00:00
* @dev Payback borrowed Coin.
* @notice Payback Coin debt owed by a Reflexer safe
2021-03-29 15:20:34 +00:00
* @param safe Safe ID.
2021-03-29 09:57:54 +00:00
* @param amt token amount to payback.
* @param getId Get token amount at this ID from `InstaMemory` Contract.
* @param setId Set token amount at this ID in `InstaMemory` Contract.
*/
function payback(
2021-03-29 15:20:34 +00:00
uint256 safe,
2021-03-29 09:57:54 +00:00
uint256 amt,
uint256 getId,
uint256 setId
) external payable returns (string memory _eventName, bytes memory _eventParam) {
uint _amt = getUint(getId, amt);
2021-03-29 15:20:34 +00:00
uint _safe = getSafe(safe);
(bytes32 collateralType, address handler) = getSafeData(_safe);
2021-03-29 09:57:54 +00:00
2021-03-29 15:20:34 +00:00
address safeEngine = managerContract.safeEngine();
2021-03-29 09:57:54 +00:00
2021-03-29 15:20:34 +00:00
uint _maxDebt = _getSafeDebt(safeEngine, collateralType, handler);
2021-03-29 09:57:54 +00:00
_amt = _amt == uint(-1) ? _maxDebt : _amt;
require(_maxDebt >= _amt, "paying-excess-debt");
approve(coinJoinContract.systemCoin(), address(coinJoinContract), _amt);
2021-03-29 15:20:34 +00:00
coinJoinContract.join(handler, _amt);
2021-03-29 09:57:54 +00:00
2021-03-29 10:34:18 +00:00
managerContract.modifySAFECollateralization(
2021-03-29 15:20:34 +00:00
_safe,
2021-03-29 09:57:54 +00:00
0,
_getWipeAmt(
2021-03-29 15:20:34 +00:00
safeEngine,
2021-03-30 10:53:38 +00:00
SafeEngineLike(safeEngine).coinBalance(handler),
2021-03-29 15:20:34 +00:00
handler,
collateralType
2021-03-29 09:57:54 +00:00
)
);
setUint(setId, _amt);
_eventName = "LogPayback(uint256,bytes32,uint256,uint256,uint256)";
2021-03-29 15:20:34 +00:00
_eventParam = abi.encode(_safe, collateralType, _amt, getId, setId);
2021-03-29 09:57:54 +00:00
}
/**
* @dev Withdraw leftover ETH/ERC20_Token after Liquidation.
* @notice Withdraw leftover collateral after Liquidation.
2021-03-29 15:20:34 +00:00
* @param safe Safe ID.
2021-03-29 09:57:54 +00:00
* @param amt token amount to Withdraw.
* @param getId Get token amount at this ID from `InstaMemory` Contract.
* @param setId Set token amount at this ID in `InstaMemory` Contract.
*/
function withdrawLiquidated(
2021-03-29 15:20:34 +00:00
uint256 safe,
2021-03-29 09:57:54 +00:00
uint256 amt,
uint256 getId,
uint256 setId
) external payable returns (string memory _eventName, bytes memory _eventParam) {
uint _amt = getUint(getId, amt);
2021-03-29 15:20:34 +00:00
(bytes32 collateralType, address handler) = getSafeData(safe);
2021-03-29 09:57:54 +00:00
2021-03-30 10:52:29 +00:00
address colAddr = getCollateralJoinAddress(collateralType);
2021-03-29 09:57:54 +00:00
TokenJoinInterface tokenJoinContract = TokenJoinInterface(colAddr);
uint _amt18;
if (_amt == uint(-1)) {
2021-03-29 15:20:34 +00:00
_amt18 = SafeEngineLike(managerContract.safeEngine()).tokenCollateral(collateralType, handler);
2021-03-29 10:34:18 +00:00
_amt = convert18ToDec(tokenJoinContract.decimals(), _amt18);
2021-03-29 09:57:54 +00:00
} else {
2021-03-29 10:34:18 +00:00
_amt18 = convertTo18(tokenJoinContract.decimals(), _amt);
2021-03-29 09:57:54 +00:00
}
2021-03-29 10:34:18 +00:00
managerContract.transferCollateral(
2021-03-29 15:20:34 +00:00
safe,
2021-03-29 09:57:54 +00:00
address(this),
_amt18
);
2021-03-29 10:34:18 +00:00
TokenInterface tokenContract = tokenJoinContract.collateral();
2021-03-29 09:57:54 +00:00
tokenJoinContract.exit(address(this), _amt);
if (isEth(address(tokenContract))) {
tokenContract.withdraw(_amt);
}
setUint(setId, _amt);
_eventName = "LogWithdrawLiquidated(uint256,bytes32,uint256,uint256,uint256)";
2021-03-29 15:20:34 +00:00
_eventParam = abi.encode(safe, collateralType, _amt, getId, setId);
2021-03-29 09:57:54 +00:00
}
2021-03-29 15:20:34 +00:00
struct GebData {
uint _safe;
2021-03-29 09:57:54 +00:00
address colAddr;
TokenJoinInterface tokenJoinContract;
2021-03-29 15:20:34 +00:00
SafeEngineLike safeEngineContract;
2021-03-29 09:57:54 +00:00
TokenInterface tokenContract;
}
2021-03-29 09:57:54 +00:00
/**
2021-03-29 15:20:34 +00:00
* @dev Deposit ETH/ERC20_Token Collateral and Borrow Coin.
* @notice Deposit collateral and borrow Coin.
2021-03-29 15:20:34 +00:00
* @param safe Safe ID.
2021-03-29 09:57:54 +00:00
* @param depositAmt token deposit amount to Withdraw.
* @param borrowAmt token borrow amount to Withdraw.
* @param getIdDeposit Get deposit token amount at this ID from `InstaMemory` Contract.
* @param getIdBorrow Get borrow token amount at this ID from `InstaMemory` Contract.
* @param setIdDeposit Set deposit token amount at this ID in `InstaMemory` Contract.
* @param setIdBorrow Set borrow token amount at this ID in `InstaMemory` Contract.
*/
function depositAndBorrow(
2021-03-29 15:20:34 +00:00
uint256 safe,
2021-03-29 09:57:54 +00:00
uint256 depositAmt,
uint256 borrowAmt,
uint256 getIdDeposit,
uint256 getIdBorrow,
uint256 setIdDeposit,
uint256 setIdBorrow
) external payable returns (string memory _eventName, bytes memory _eventParam) {
2021-03-29 15:20:34 +00:00
GebData memory gebData;
2021-03-29 09:57:54 +00:00
uint _amtDeposit = getUint(getIdDeposit, depositAmt);
uint _amtBorrow = getUint(getIdBorrow, borrowAmt);
2021-03-29 15:20:34 +00:00
gebData._safe = getSafe(safe);
(bytes32 collateralType, address handler) = getSafeData(gebData._safe);
2021-03-29 09:57:54 +00:00
2021-03-30 10:52:29 +00:00
gebData.colAddr = getCollateralJoinAddress(collateralType);
2021-03-29 15:20:34 +00:00
gebData.tokenJoinContract = TokenJoinInterface(gebData.colAddr);
gebData.safeEngineContract = SafeEngineLike(managerContract.safeEngine());
gebData.tokenContract = gebData.tokenJoinContract.collateral();
2021-03-29 09:57:54 +00:00
2021-03-29 15:20:34 +00:00
if (isEth(address(gebData.tokenContract))) {
2021-03-29 09:57:54 +00:00
_amtDeposit = _amtDeposit == uint(-1) ? address(this).balance : _amtDeposit;
2021-03-29 15:20:34 +00:00
gebData.tokenContract.deposit{value: _amtDeposit}();
2021-03-29 09:57:54 +00:00
} else {
2021-03-29 15:20:34 +00:00
_amtDeposit = _amtDeposit == uint(-1) ? gebData.tokenContract.balanceOf(address(this)) : _amtDeposit;
2021-03-29 09:57:54 +00:00
}
approve(gebData.tokenContract, address(gebData.colAddr), _amtDeposit);
2021-03-29 15:20:34 +00:00
gebData.tokenJoinContract.join(handler, _amtDeposit);
2021-03-29 09:57:54 +00:00
2021-03-29 10:34:18 +00:00
managerContract.modifySAFECollateralization(
2021-03-29 15:20:34 +00:00
gebData._safe,
toInt(convertTo18(gebData.tokenJoinContract.decimals(), _amtDeposit)),
2021-03-29 09:57:54 +00:00
_getBorrowAmt(
2021-03-29 15:20:34 +00:00
address(gebData.safeEngineContract),
handler,
collateralType,
2021-03-29 09:57:54 +00:00
_amtBorrow
)
);
2021-03-29 10:34:18 +00:00
managerContract.transferInternalCoins(
2021-03-29 15:20:34 +00:00
gebData._safe,
2021-03-29 09:57:54 +00:00
address(this),
toRad(_amtBorrow)
);
2021-03-29 15:20:34 +00:00
if (gebData.safeEngineContract.safeRights(address(this), address(coinJoinContract)) == 0) {
gebData.safeEngineContract.approveSAFEModification(address(coinJoinContract));
2021-03-29 09:57:54 +00:00
}
2021-03-29 15:20:34 +00:00
coinJoinContract.exit(address(this), _amtBorrow);
2021-03-29 09:57:54 +00:00
setUint(setIdDeposit, _amtDeposit);
setUint(setIdBorrow, _amtBorrow);
_eventName = "LogDepositAndBorrow(uint256,bytes32,uint256,uint256,uint256,uint256,uint256,uint256)";
_eventParam = abi.encode(
2021-03-29 15:20:34 +00:00
gebData._safe,
collateralType,
2021-03-29 09:57:54 +00:00
_amtDeposit,
_amtBorrow,
getIdDeposit,
getIdBorrow,
setIdDeposit,
setIdBorrow
);
}
/**
2021-03-29 15:20:34 +00:00
* @dev Exit Coin from handler.
* @notice Exit Coin from handler.
2021-03-29 15:20:34 +00:00
* @param safe Safe ID.
2021-03-29 09:57:54 +00:00
* @param amt token amount to exit.
* @param getId Get token amount at this ID from `InstaMemory` Contract.
* @param setId Set token amount at this ID in `InstaMemory` Contract.
*/
2021-03-29 15:20:34 +00:00
function exit(
uint256 safe,
2021-03-29 09:57:54 +00:00
uint256 amt,
uint256 getId,
uint256 setId
) external payable returns (string memory _eventName, bytes memory _eventParam) {
uint _amt = getUint(getId, amt);
2021-03-29 15:20:34 +00:00
uint _safe = getSafe(safe);
(bytes32 collateralType, address handler) = getSafeData(_safe);
2021-03-29 09:57:54 +00:00
2021-03-29 15:20:34 +00:00
SafeEngineLike safeEngineContract = SafeEngineLike(managerContract.safeEngine());
2021-03-29 09:57:54 +00:00
if(_amt == uint(-1)) {
2021-03-30 10:53:38 +00:00
_amt = safeEngineContract.coinBalance(handler);
2021-03-29 09:57:54 +00:00
_amt = _amt / 10 ** 27;
}
2021-03-29 10:34:18 +00:00
managerContract.transferInternalCoins(
2021-03-29 15:20:34 +00:00
_safe,
2021-03-29 09:57:54 +00:00
address(this),
toRad(_amt)
);
2021-03-29 15:20:34 +00:00
if (safeEngineContract.safeRights(address(this), address(coinJoinContract)) == 0) {
safeEngineContract.approveSAFEModification(address(coinJoinContract));
2021-03-29 09:57:54 +00:00
}
2021-03-29 15:20:34 +00:00
coinJoinContract.exit(address(this), _amt);
2021-03-29 09:57:54 +00:00
setUint(setId, _amt);
2021-03-29 15:20:34 +00:00
_eventName = "LogExit(uint256,bytes32,uint256,uint256,uint256)";
_eventParam = abi.encode(_safe, collateralType, _amt, getId, setId);
2021-03-29 09:57:54 +00:00
}
}
2021-03-29 15:20:34 +00:00
contract ConnectV2Reflexer is GebResolver {
string public constant name = "Reflexer-v1";
2021-03-29 09:57:54 +00:00
}