From f07e06e6ac1555c7dcc9f374ab834172f3c003fa Mon Sep 17 00:00:00 2001 From: q1q0 Date: Sun, 30 Jul 2023 13:00:04 -0400 Subject: [PATCH] add crv connector --- .../mainnet/connectors/crv_USD/events.sol | 11 + .../mainnet/connectors/crv_USD/helpers.sol | 23 +++ .../mainnet/connectors/crv_USD/interface.sol | 20 ++ contracts/mainnet/connectors/crv_USD/main.sol | 195 ++++++++++++++++++ 4 files changed, 249 insertions(+) create mode 100644 contracts/mainnet/connectors/crv_USD/events.sol create mode 100644 contracts/mainnet/connectors/crv_USD/helpers.sol create mode 100644 contracts/mainnet/connectors/crv_USD/interface.sol create mode 100644 contracts/mainnet/connectors/crv_USD/main.sol diff --git a/contracts/mainnet/connectors/crv_USD/events.sol b/contracts/mainnet/connectors/crv_USD/events.sol new file mode 100644 index 00000000..64937640 --- /dev/null +++ b/contracts/mainnet/connectors/crv_USD/events.sol @@ -0,0 +1,11 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; + +contract Events { + event LogCreateLoan(address indexed collateral, uint256 amt, uint256 debt, uint256 indexed N); + event LogAddCollateral(address indexed collateral, uint256 indexed amt, uint256 getId, uint256 setId); + event LogRemoveCollateral(address indexed collateral, uint256 indexed amt, uint256 getId, uint256 setId); + event LogBorrowMore(address indexed collateral, uint256 indexed amt, uint256 indexed debt); + event LogRepay(address indexed collateral, uint256 indexed amt, uint256 getId, uint256 setId); + event LogLiquidate(address indexed collateral, uint256 indexed min_x); +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/crv_USD/helpers.sol b/contracts/mainnet/connectors/crv_USD/helpers.sol new file mode 100644 index 00000000..c0d439c6 --- /dev/null +++ b/contracts/mainnet/connectors/crv_USD/helpers.sol @@ -0,0 +1,23 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; + +import { DSMath } from "../../common/math.sol"; +import { Basic } from "../../common/basic.sol"; +import { TokenInterface } from "../../common/interfaces.sol"; +import "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + + address internal constant CRV_USD = 0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E; + /** + * @dev ControllerFactory Interface + */ + IControllerFactory internal constant ctrFactory = IControllerFactory(0xC9332fdCB1C491Dcc683bAe86Fe3cb70360738BC); + + /** + * @dev Get controller address by given collateral asset + */ + function getController(address collateral) internal view returns(IController controller) { + controller = IController(ctrFactory.get_controller(collateral, 0)); + } +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/crv_USD/interface.sol b/contracts/mainnet/connectors/crv_USD/interface.sol new file mode 100644 index 00000000..df2856ac --- /dev/null +++ b/contracts/mainnet/connectors/crv_USD/interface.sol @@ -0,0 +1,20 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; + +import { TokenInterface } from "../../common/interfaces.sol"; + +interface IControllerFactory { + function get_controller(address collateral, uint256 index) external view returns (address); +} + +interface IController { + function create_loan(uint256 collateral, uint256 debt, uint256 N) payable external; + function add_collateral(uint256 collateral, address _for) payable external; + function remove_collateral(uint256 collateral, bool use_eth) external; + function borrow_more(uint256 collateral, uint256 debt) payable external; + function repay(uint256 _d_debt, address _for, int256 max_active_band, bool use_eth) payable external; + function liquidate(address user, uint256 min_x, bool use_eth) external; + function max_borrowable(uint256 collateral, uint256 N) external view returns(uint256); + function min_collateral(uint256 debt, uint256 N) external view returns(uint256); + function user_state(address user) external view returns(uint256[] memory); +} diff --git a/contracts/mainnet/connectors/crv_USD/main.sol b/contracts/mainnet/connectors/crv_USD/main.sol new file mode 100644 index 00000000..d55503ab --- /dev/null +++ b/contracts/mainnet/connectors/crv_USD/main.sol @@ -0,0 +1,195 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; + +/** + * @title MakerDAO. + * @dev Collateralized Borrowing. + */ + +import { TokenInterface, AccountInterface } from "../../common/interfaces.sol"; +import { Helpers } from "./helpers.sol"; +import { Events } from "./events.sol"; +import "./interface.sol"; + +abstract contract MakerResolver is Helpers, Events { + /** + * @dev Create loan + * @param collateral collateral token address + * @param amt Amount of collateral to use + * @param debt Stablecoin debt to take + * @param N Number of bands to deposit into (to do autoliquidation-deliquidation), can be from MIN_TICKS(4) to MAX_TICKS(50) + */ + function createLoan( + address collateral, + uint256 amt, + uint256 debt, + uint256 N + ) external returns (string memory _eventName, bytes memory _eventParam) { + address _collateral = collateral == ethAddr ? wethAddr : collateral; + IController controller = getController(_collateral); + uint256 _amt = amt; + + uint256 ethAmt; + if (collateral == ethAddr) { + _amt = _amt == uint(-1) ? address(this).balance : _amt; + ethAmt = _amt; + } else { + TokenInterface collateralContract = TokenInterface(_collateral); + _amt = _amt == uint(-1) ? collateralContract.balanceOf(address(this)) : _amt; + approve(collateralContract, address(controller), _amt); + } + + uint256 _debt = debt == uint(-1) ? controller.max_borrowable(_amt, N) : debt; + + controller.create_loan{value: ethAmt}(_amt, _debt, N); + _eventName = "LogCreateLoan(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(collateral, amt, debt, N); + } + + /** + * @dev Add collateral + * @notice Add extra collateral to avoid bad liqidations + * @param collateral collateral asset address + * @param amt Amount of collateral to add + * @param getId ID to retrieve amt. + * @param setId ID stores the collateral amount of tokens added. + */ + function addCollateral( + address collateral, + uint256 amt, + uint256 getId, + uint256 setId + ) external returns (string memory _eventName, bytes memory _eventParam) { + address _collateral = collateral == ethAddr ? wethAddr : collateral; + IController controller = getController(_collateral); + uint _amt = getUint(getId, amt); + + uint ethAmt; + if (collateral == ethAddr) { + _amt = _amt == uint(-1) ? address(this).balance : _amt; + ethAmt = _amt; + } else { + TokenInterface collateralContract = TokenInterface(_collateral); + _amt = _amt == uint(-1) ? collateralContract.balanceOf(address(this)) : _amt; + approve(collateralContract, address(controller), _amt); + } + + controller.add_collateral{value: ethAmt}(_amt, address(this)); + + setUint(setId, _amt); + _eventName = "LogAddCollateral(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(collateral, amt, getId, setId); + } + + /** + * @dev Remove ETH/ERC20_Token Collateral. + * @notice Remove some collateral without repaying the debt + * @param collateral collateral asset address + * @param amt Amount of collateral to add + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens deposited. + */ + function removeCollateral( + address collateral, + uint256 amt, + uint256 getId, + uint256 setId + ) external returns (string memory _eventName, bytes memory _eventParam) { + address _collateral = collateral == ethAddr ? wethAddr : collateral; + IController controller = getController(_collateral); + uint _amt = getUint(getId, amt); + + controller.remove_collateral(_amt, collateral == ethAddr); + + setUint(setId, _amt); + + _eventName = "LogRemoveCollateral(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(collateral, amt, getId, setId); + } + + /** + * @dev Borrow more stablecoins while adding more collateral (not necessary) + * @param collateral collateral token address + * @param amt Amount of collateral to add + * @param debt Amount of stablecoin debt to take + */ + function borrowMore( + address collateral, + uint256 amt, + uint256 debt + ) external returns (string memory _eventName, bytes memory _eventParam) { + address _collateral = collateral == ethAddr ? wethAddr : collateral; + IController controller = getController(_collateral); + uint _amt = amt; + + uint ethAmt; + if (collateral == ethAddr) { + _amt = _amt == uint(-1) ? address(this).balance : _amt; + ethAmt = _amt; + } else { + TokenInterface collateralContract = TokenInterface(_collateral); + _amt = _amt == uint(-1) ? collateralContract.balanceOf(address(this)) : _amt; + approve(collateralContract, address(controller), _amt); + } + + uint256[] memory res = controller.user_state(address(this)); + + uint256 _debt = debt == uint(-1) ? controller.max_borrowable(_amt, res[3]) : debt; + + controller.borrow_more{value: ethAmt}(_amt, _debt); + + _eventName = "LogBorrowMore(address,uint256,uint256)"; + _eventParam = abi.encode(collateral, amt, debt); + } + + /** + * @dev Borrow DAI. + * @notice Borrow DAI using a MakerDAO vault + * @param collateral collateral token address + * @param amt The amount of debt to repay. If higher than the current debt - will do full repayment + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of DAI borrowed. + */ + function repay( + address collateral, + uint256 amt, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + address _collateral = collateral == ethAddr ? wethAddr : collateral; + IController controller = getController(_collateral); + uint _amt = amt; + + TokenInterface stableCoin = TokenInterface(CRV_USD); + _amt = _amt == uint(-1) ? stableCoin.balanceOf(address(this)) : _amt; + TokenInterface collateralContract = TokenInterface(_collateral); + approve(collateralContract, address(controller), _amt); + + controller.repay(_amt, address(this), 2**255-1, true); + + _eventName = "LogRepay(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(collateral, amt, getId, setId); + } + + /** + * @dev Peform a bad liquidation (or self-liquidation) of user if health is not good + * @param collateral collateral token address + * @param min_x Minimal amount of stablecoin to receive (to avoid liquidators being sandwiched) + */ + function liquidate( + address collateral, + uint256 min_x + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + address _collateral = collateral == ethAddr ? wethAddr : collateral; + IController controller = getController(_collateral); + + controller.liquidate(address(this), min_x, collateral == ethAddr); + + _eventName = "LogLiquidate(address,uint256)"; + _eventParam = abi.encode(collateral, min_x); + } +} + +contract ConnectV2MakerDAO is MakerResolver { + string public constant name = "CRV-USD-v1"; +} \ No newline at end of file