diff --git a/contracts/protocols/mainnet/crvusd/helpers.sol b/contracts/protocols/mainnet/crvusd/helpers.sol index 8bc4772..2e579fb 100644 --- a/contracts/protocols/mainnet/crvusd/helpers.sol +++ b/contracts/protocols/mainnet/crvusd/helpers.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0; +pragma solidity ^0.8.6; import "./interfaces.sol"; import { DSMath } from "../../../utils/dsmath.sol"; @@ -42,6 +42,9 @@ contract CRVHelpers is DSMath { config.borrowable = IERC20(CRV_USD).balanceOf(address(controller)); config.basePrice = I_LLAMMA(AMM).get_base_price(); config.A = I_LLAMMA(AMM).A(); + config.minBand = I_LLAMMA(AMM).min_band(); + config.maxBand = I_LLAMMA(AMM).max_band(); + try IMonetary(monetary).rate(address(controller)) returns (uint256 rate) { config.fractionPerSecond = rate; } catch { diff --git a/contracts/protocols/mainnet/crvusd/interfaces.sol b/contracts/protocols/mainnet/crvusd/interfaces.sol index e5e3bb5..d453fd4 100644 --- a/contracts/protocols/mainnet/crvusd/interfaces.sol +++ b/contracts/protocols/mainnet/crvusd/interfaces.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0; +pragma solidity ^0.8.0; struct PositionData { uint256 supply; @@ -9,6 +9,7 @@ struct PositionData { uint256 health; UserPrices prices; uint256 loanId; + int256[2] userTickNumber; // calculating for user band range } struct UserPrices { @@ -39,6 +40,8 @@ struct MarketConfig { address monetary; uint256 borrowable; Coins coins; // factors for total collaterals + int256 minBand; + int256 maxBand; } interface IControllerFactory { @@ -71,6 +74,16 @@ interface IController { function amm_price() external view returns (uint256); function monetary_policy() external view returns (address); + + function max_borrowable(uint256 collateral, uint256 N) external view returns (uint256); + + function min_collateral(uint256 debt, uint256 N) external view returns (uint256); + + function calculate_debt_n1( + uint256 collateral, + uint256 debt, + uint256 N + ) external view returns (int256); } interface I_LLAMMA { @@ -81,6 +94,16 @@ interface I_LLAMMA { function coins(uint256 i) external view returns (address); function get_base_price() external view returns (uint256); + + function read_user_tick_numbers(address user) external view returns (int256[2] memory); + + function min_band() external view returns (int256); + + function max_band() external view returns (int256); + + function p_oracle_up(int256 bandNumber0) external view returns (uint256); + + function p_oracle_down(int256 bandNumber1) external view returns (uint256); } interface IMonetary { diff --git a/contracts/protocols/mainnet/crvusd/main.sol b/contracts/protocols/mainnet/crvusd/main.sol index b90f3bc..21e8064 100644 --- a/contracts/protocols/mainnet/crvusd/main.sol +++ b/contracts/protocols/mainnet/crvusd/main.sol @@ -23,6 +23,8 @@ contract CurveUSDResolver is CRVHelpers { ) public view returns (PositionData memory positionData, MarketConfig memory marketConfig) { IController controller = getController(market, index); uint256[4] memory res = controller.user_state(user); + address AMM = controller.amm(); + positionData.userTickNumber = I_LLAMMA(AMM).read_user_tick_numbers(user); positionData.borrow = res[2]; positionData.supply = res[0]; positionData.N = res[3]; @@ -92,6 +94,66 @@ contract CurveUSDResolver is CRVHelpers { marketConfig[i] = getMarketConfig(markets[i], indexes[i]); } } + + /** + *@dev get max debt amount with given collateral. + *@param market Addresse of the market + *@param version Latest controller version + *@return debt Max debt amount. + */ + function getMaxDebt( + address market, + uint256 version, + uint256 collateralAmount, + uint256 bandNumber + ) public view returns (uint256 debt) { + IController controller = getController(market, version); + return controller.max_borrowable(collateralAmount, bandNumber); + } + + /** + *@dev get min collateral amount with given debt. + *@param market Addresse of the market + *@param version Latest controller version + *@return collateral Min collateral amount. + */ + function getMinCollateral( + address market, + uint256 version, + uint256 debt, + uint256 bandNumber + ) public view returns (uint256 collateral) { + IController controller = getController(market, version); + return controller.min_collateral(debt, bandNumber); + } + + /** + *@dev get band range according to given collateral, debt and bandNumber. + *@param market Addresse of the market + *@param version Latest controller version + *@param collateral collateral amount. + *@param debt debt amount. + *@return range Band range. + *@return liquidation liquidation price range. + */ + function getBandRangeAndLiquidationRange( + address market, + uint256 version, + uint256 collateral, + uint256 debt, + uint256 bandNumber + ) public view returns (int256[2] memory range, uint256[2] memory liquidation) { + IController controller = getController(market, version); + address AMM = controller.amm(); + int256 minBand = I_LLAMMA(AMM).min_band(); + int256 maxBand = I_LLAMMA(AMM).max_band(); + require(int256(bandNumber) >= minBand && int256(bandNumber) <= maxBand, "Invalid band number"); + + range[0] = controller.calculate_debt_n1(collateral, debt, bandNumber); + range[1] = range[0] + int256(bandNumber) - 1; + liquidation[0] = I_LLAMMA(AMM).p_oracle_up(range[0]); + liquidation[1] = I_LLAMMA(AMM).p_oracle_down(range[1]); + } } contract InstaCurveUSDResolver is CurveUSDResolver { diff --git a/test/mainnet/crv_usd.test.ts b/test/mainnet/crv_usd.test.ts index 7b4d7dc..be6933b 100644 --- a/test/mainnet/crv_usd.test.ts +++ b/test/mainnet/crv_usd.test.ts @@ -59,6 +59,8 @@ describe("CRV-USD Resolvers", () => { console.log(`Coin1 token decimals: ${market.coins.coin1Decimals}`); console.log(`Coin0 balance: ${market.coins.coin0Amount}`); console.log(`Coin1 balance: ${market.coins.coin1Amount}`); + console.log(`min Band: ${market.minBand}`); + console.log(`max Band: ${market.maxBand}`); console.log("======================================================"); } }); @@ -77,8 +79,30 @@ describe("CRV-USD Resolvers", () => { console.log(`Use loan ID: ${position.loanId}`); console.log(`User upper price: ${position.prices.upper}`); console.log(`User lower price: ${position.prices.lower}`); + console.log(`User userTickNumber: ${position.userTickNumber}`); console.log("-----------------------------------------------------------"); } }); + + it("Returns max debt amount", async () => { + const maxDebt = await resolver.getMaxDebt(markets[0], 0, "1000000000000000000", 12); + console.log("maxDebt amount: ", maxDebt); + }); + + it("Returns min collateral amount", async () => { + const minCollateral = await resolver.getMinCollateral(markets[0], 0, "500000000000000000000", 10); + console.log("minCollateral amount: ", minCollateral); + }); + + it("Returns Band range", async () => { + const minCollateral = await resolver.getBandRangeAndLiquidationRange( + markets[0], + 0, + "2205663198573977494528", + "2589469072122129017791488", + 21, + ); + console.log("maxDebt amount: ", minCollateral); + }); }); });