Skip to content

Commit

Permalink
simplifies dai dsr asset by investing in spark sdai
Browse files Browse the repository at this point in the history
  • Loading branch information
maxcoto committed Dec 14, 2023
1 parent 0c61742 commit 9b4c4e6
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 177 deletions.
168 changes: 69 additions & 99 deletions contracts/Assets/DsrAsset.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,71 +10,68 @@ pragma solidity 0.8.19;
* @dev Representation of an on-chain investment on a DAI
*/

import "./Interfaces/DAI/IDsrManager.sol";
import "./Interfaces/DAI/IPot.sol";
import "./Interfaces/DAI/IPsm.sol";
import "../Libraries/RMath.sol";
import "../Stabilizer/Stabilizer.sol";
import { IERC20Metadata } from "@openzeppelin/contracts/interfaces/IERC20Metadata.sol";
import { IERC4626 } from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import { IPSM } from "./Interfaces/DAI/IPSM.sol";
import { Stabilizer, IPriceFeed, OvnMath, TransferHelper, ChainlinkLibrary } from "../Stabilizer/Stabilizer.sol";

contract DsrAsset is Stabilizer {
IERC20Metadata private immutable dai;
IDsrManager private immutable dsrManager;
IPot private immutable pot;
IPsm private immutable psm;
IPriceFeed private immutable oracleDai;

address private immutable gemJoin;
uint256 private constant WAD = 10 ** 18;
IERC20Metadata private immutable dai;
IERC4626 private immutable sDai;
IPSM private immutable psm;

uint256 private constant WAD = 1e18;

// Events
event Invested(uint256 indexed usdxAmount);
event Divested(uint256 indexed usdxAmount);

// Errors
error UnExpectedAmount();
error UnexpectedAmount();

constructor(
string memory _name,
address _sweep,
address _usdx,
address _dai,
address _dsrManager,
address _dssPsm,
address _sDai,
address _psm,
address _oracleUsdx,
address _oracleDai,
address _borrower
) Stabilizer(_name, _sweep, _usdx, _oracleUsdx, _borrower) {
dai = IERC20Metadata(_dai);
dsrManager = IDsrManager(_dsrManager);
pot = IPot(dsrManager.pot());
psm = IPsm(_dssPsm);
gemJoin = psm.gemJoin();
sDai = IERC4626(_sDai);
psm = IPSM(_psm);
oracleDai = IPriceFeed(_oracleDai);
}

/* ========== Views ========== */

/**
* @notice Get Asset Value
* @return uint256 Asset Amount.
* @dev the invested amount in USDX on the DSR.
* @notice Asset Value of investment.
* @return the Returns the value of the investment in the USD coin
* @dev the price is obtained from the target asset
*/
function assetValue() public view override returns (uint256) {
uint256 daiAmount = dsrManager.pieOf(address(this));
uint256 chi = pot.chi();
daiAmount = RMath.rmul(chi, daiAmount); // included reward
function assetValue() public view virtual override returns (uint256) {
uint256 sharesBalance = sDai.balanceOf(address(this));
uint256 assetsBalance = sDai.convertToAssets(sharesBalance);

return _oracleDaiToUsd(daiAmount);
return _oracleDaiToUsd(assetsBalance);
}

/* ========== Actions ========== */

/**
* @notice dsrDaiBalance
* @dev Get the invested dai amount
* @notice Liquidate
* @dev When the asset is defaulted anyone can liquidate it by
* repaying the debt and getting the same value at a discount.
*/
function dsrDaiBalance() external nonReentrant returns (uint256) {
return dsrManager.daiBalance(address(this));
function liquidate() external virtual nonReentrant {
if(auctionAllowed) revert ActionNotAllowed();
_liquidate(_getToken(), getDebt());
}

/**
Expand All @@ -83,10 +80,9 @@ contract DsrAsset is Stabilizer {
* @param slippage .
* @dev Sends balance to DSR.
*/
function invest(
uint256 usdxAmount,
uint256 slippage
) external onlyBorrower whenNotPaused nonReentrant validAmount(usdxAmount) {
function invest(uint256 usdxAmount, uint256 slippage)
external onlyBorrower whenNotPaused nonReentrant validAmount(usdxAmount)
{
_invest(usdxAmount, 0, slippage);
}

Expand All @@ -96,67 +92,45 @@ contract DsrAsset is Stabilizer {
* @param slippage .
* @dev Sends balance from the DSR to the Asset.
*/
function divest(
uint256 usdxAmount,
uint256 slippage
)
external
onlyBorrower
nonReentrant
validAmount(usdxAmount)
function divest(uint256 usdxAmount, uint256 slippage)
external onlyBorrower nonReentrant validAmount(usdxAmount)
returns (uint256)
{
return _divest(usdxAmount, slippage);
}

/**
* @notice Liquidate
* @dev When the asset is defaulted anyone can liquidate it by
* repaying the debt and getting the same value at a discount.
*/
function liquidate() external nonReentrant {
if(auctionAllowed) revert ActionNotAllowed();
_liquidate(address(dai), getDebt());
}

/* ========== Internals ========== */

function _getToken() internal view override returns (address) {
return address(dai);
return address(sDai);
}

/**
* @notice Invest
* @dev Deposits the amount into the DSR.
*/
function _invest(
uint256 usdxAmount,
uint256,
uint256 slippage
) internal override {
function _invest(uint256 usdxAmount, uint256, uint256 slippage)
internal override
{
uint256 usdxBalance = usdx.balanceOf(address(this));
uint256 daiBalance = dai.balanceOf(address(this));
if (usdxBalance == 0) revert NotEnoughBalance();
if (usdxBalance < usdxAmount) usdxAmount = usdxBalance;

// Exchange Usdx to Dai by using PSM
uint256 estimatedAmount = _usdxToDai(
OvnMath.subBasisPoints(usdxAmount, slippage)
);
TransferHelper.safeApprove(address(usdx), address(gemJoin), usdxAmount);
TransferHelper.safeApprove(address(usdx), psm.gemJoin(), usdxAmount);
psm.sellGem(address(this), usdxAmount);
uint256 investDaiAmount = dai.balanceOf(address(this)) - daiBalance;

// Check return amount validation
if (investDaiAmount == 0 || investDaiAmount < estimatedAmount)
revert UnExpectedAmount();
uint256 estimatedAmount = _usdxToDai(OvnMath.subBasisPoints(usdxAmount, slippage));
uint256 investDaiAmount = dai.balanceOf(address(this)) - daiBalance;
if (investDaiAmount == 0 || investDaiAmount < estimatedAmount) {
revert UnexpectedAmount();
}

// Invest Dai to the dsr
TransferHelper.safeApprove(
address(dai),
address(dsrManager),
investDaiAmount
);
dsrManager.join(address(this), investDaiAmount);
TransferHelper.safeApprove(address(dai), address(sDai), investDaiAmount);
sDai.deposit(investDaiAmount, address(this));

emit Invested(_daiToUsdx(investDaiAmount));
}
Expand All @@ -168,43 +142,39 @@ contract DsrAsset is Stabilizer {
function _divest(
uint256 usdxAmount,
uint256 slippage
) internal override returns (uint256 divestedAmount) {
uint256 usdxBalance = usdx.balanceOf(address(this));
uint256 daiBalance = dai.balanceOf(address(this));
uint256 daiAmount = _oracleUsdxToDai(usdxAmount);
uint256 investedAmount = dsrManager.daiBalance(address(this));

// Withdraw Dai from DSR
if (daiAmount < investedAmount) {
dsrManager.exit(address(this), daiAmount);
} else {
dsrManager.exitAll(address(this));
daiAmount = investedAmount;
}
uint256 redeemDaiAmount = dai.balanceOf(address(this)) - daiBalance;
) internal override returns (uint256) {
uint256 initialDaiBalance = dai.balanceOf(address(this));
uint256 initialUsdxBalance = usdx.balanceOf(address(this));

uint256 sharesBalance = sDai.balanceOf(address(this));
if (sharesBalance == 0) revert NotEnoughBalance();
uint256 sharesAmount = sDai.convertToShares(usdxAmount);
if (sharesBalance > sharesAmount) sharesAmount = sharesBalance;

uint256 withdrawAmount = sDai.convertToAssets(sharesAmount);
sDai.withdraw(withdrawAmount, address(this), address(this));

// Check return amount from dsrManager
if (redeemDaiAmount == 0 || redeemDaiAmount < daiAmount)
revert UnExpectedAmount();
uint256 daiBalance = dai.balanceOf(address(this)) - initialDaiBalance;
if (daiBalance == 0 || daiBalance < withdrawAmount) revert UnexpectedAmount();

// Exchange Dai to Usdx by using PSM
uint256 estimatedAmount = _daiToUsdx(
OvnMath.subBasisPoints(redeemDaiAmount, slippage)
);
TransferHelper.safeApprove(address(dai), address(psm), redeemDaiAmount);
TransferHelper.safeApprove(address(dai), address(psm), daiBalance);
withdrawAmount = _daiToUsdx(OvnMath.subBasisPoints(daiBalance, slippage));

// Reduce fee from the request Usdx amount
uint256 psmFee = psm.tout();
redeemDaiAmount = (redeemDaiAmount * WAD) / (WAD + psmFee);
uint256 daiInUsdx = _daiToUsdx(redeemDaiAmount);
daiBalance = (daiBalance * WAD) / (WAD + psmFee);
uint256 daiInUsdx = _daiToUsdx(daiBalance);
psm.buyGem(address(this), daiInUsdx);

// Sanity check && Calculate real divested Usdx amount
if (
estimatedAmount >
(divestedAmount = usdx.balanceOf(address(this)) - usdxBalance)
) revert UnExpectedAmount();
// Calculate real divested Usdx amount
uint256 usdxBalance = usdx.balanceOf(address(this)) - initialUsdxBalance;
// Sanity check
if (usdxBalance < withdrawAmount) revert UnexpectedAmount();

emit Divested(divestedAmount);
emit Divested(usdxBalance);
return usdxBalance;
}

/**
Expand Down
1 change: 0 additions & 1 deletion contracts/Assets/ERC20Asset.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ pragma solidity 0.8.19;
* @dev Representation of an on-chain investment like Wrapped Ether, Wrapped Bitcoin ...
*/

import { IERC4626 } from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import { Stabilizer, IPriceFeed, IAMM, ChainlinkLibrary, OvnMath, TransferHelper, IERC20Metadata } from "../Stabilizer/Stabilizer.sol";
import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import { IUniswapV3Pool } from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";
Expand Down
6 changes: 3 additions & 3 deletions contracts/Assets/GDAIAsset.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pragma solidity 0.8.19;
*/

import "./Interfaces/GDAI/IGToken.sol";
import "./Interfaces/DAI/IPsm.sol";
import "./Interfaces/DAI/IPSM.sol";
import "./Interfaces/GDAI/IOpenTradesPnlFeed.sol";
import "../Stabilizer/Stabilizer.sol";

Expand All @@ -20,7 +20,7 @@ contract GDAIAsset is Stabilizer {
IERC20Metadata private immutable dai;
IOpenTradesPnlFeed private immutable openTradesPnlFeed;
IPriceFeed private immutable oracleDai;
IPsm private immutable psm;
IPSM private immutable psm;

// Variables
address private immutable gemJoin;
Expand Down Expand Up @@ -55,7 +55,7 @@ contract GDAIAsset is Stabilizer {
) Stabilizer(_name, _sweep, _usdx, _oracleUsdx, _borrower) {
gDai = IGToken(_gDai);
dai = IERC20Metadata(gDai.asset());
psm = IPsm(_dssPsm);
psm = IPSM(_dssPsm);
gemJoin = psm.gemJoin();
openTradesPnlFeed = IOpenTradesPnlFeed(gDai.openTradesPnlFeed());
oracleDai = IPriceFeed(_oracleDai);
Expand Down
16 changes: 0 additions & 16 deletions contracts/Assets/Interfaces/DAI/IDsrManager.sol

This file was deleted.

6 changes: 0 additions & 6 deletions contracts/Assets/Interfaces/DAI/IPot.sol

This file was deleted.

2 changes: 1 addition & 1 deletion contracts/Assets/Interfaces/DAI/IPsm.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;

interface IPsm {
interface IPSM {
function tout() external view returns (uint256);

function daiJoin() external view returns (address);
Expand Down
Loading

0 comments on commit 9b4c4e6

Please sign in to comment.