Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions script/SetParameters.s.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ITroveManager} from "../src/core/interfaces/ITroveManager.sol";
import { ITroveManager } from "../src/core/interfaces/ITroveManager.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { Script, console2 } from "forge-std/Script.sol";

Expand All @@ -14,7 +14,7 @@ uint256 constant MAX_BORROWING_FEE = 1e18 / 100 * 5; // (5%)
uint256 constant INTEREST_RATE_IN_BPS = 0; // (0%)
uint256 constant MAX_DEBT = 1e18 * 1_000_000_000;
uint256 constant MCR = 170 * 1e16; // 110 * 1e16 -> 110%
uint128 constant REWARD_RATE = 0;
uint128 constant REWARD_RATE = 0;
uint32 constant TM_CLAIM_START_TIME = 4_294_967_295; // max uint32

contract SetParametersScript is Script {
Expand Down
2 changes: 1 addition & 1 deletion script/priceFeed/DeployPriceFeedChainlink.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Script, console2 } from "forge-std/Script.sol";

//! Change when deploying
address constant CHAINLINK_PRICE_FEED_SOURCE_ADDRESS = 0x31a36CdF4465ba61ce78F5CDbA26FDF8ec361803;
uint256 constant CHAINLINK_MAX_TIME_THRESHOLD = 21600 + 300;
uint256 constant CHAINLINK_MAX_TIME_THRESHOLD = 21_600 + 300;

contract DeployPriceFeedChainlinkScript is Script {
PriceFeedChainlink internal priceFeedChainlink;
Expand Down
220 changes: 219 additions & 1 deletion src/core/helpers/SatoshiPeriphery.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ import { DebtTokenWithLz } from "../DebtTokenWithLz.sol";
import { IBorrowerOperationsFacet } from "../interfaces/IBorrowerOperationsFacet.sol";
import { ICoreFacet } from "../interfaces/ICoreFacet.sol";
import { ILiquidationFacet } from "../interfaces/ILiquidationFacet.sol";

import { IPriceFeedAggregatorFacet } from "../interfaces/IPriceFeedAggregatorFacet.sol";
import { ITroveManager } from "../interfaces/ITroveManager.sol";

import { ISupraOraclePull } from "../../priceFeed/interfaces/ISupraOraclePull.sol";
import { IDebtToken } from "../interfaces/IDebtToken.sol";
import { ISatoshiPeriphery, LzSendParam } from "./interfaces/ISatoshiPeriphery.sol";
import { IWETH } from "./interfaces/IWETH.sol";
Expand Down Expand Up @@ -93,6 +96,38 @@ contract SatoshiPeriphery is ISatoshiPeriphery, UUPSUpgradeable, OwnableUpgradea
_afterWithdrawDebt(userDebtAmount, _lzSendParam);
}

function openTroveWithSupraPriceUpdate(
ITroveManager troveManager,
uint256 _maxFeePercentage,
uint256 _collAmount,
uint256 _debtAmount,
address _upperHint,
address _lowerHint,
LzSendParam calldata _lzSendParam,
bytes calldata _bytesProof
)
external
payable
{
IERC20 collateralToken = troveManager.collateralToken();

_updateSupraPriceFeed(troveManager, _bytesProof);

_beforeAddColl(collateralToken, _collAmount);

uint256 debtTokenBalanceBefore = debtToken.balanceOf(address(this));

IBorrowerOperationsFacet(xApp).openTrove(
troveManager, msg.sender, _maxFeePercentage, _collAmount, _debtAmount, _upperHint, _lowerHint
);

uint256 debtTokenBalanceAfter = debtToken.balanceOf(address(this));
uint256 userDebtAmount = debtTokenBalanceAfter - debtTokenBalanceBefore;
require(userDebtAmount == _debtAmount, "SatoshiPeriphery: Debt amount mismatch");

_afterWithdrawDebt(userDebtAmount, _lzSendParam);
}

/// @notice Add collateral to a active trove
/// @param troveManager The TroveManager contract
/// @param _collAmount The amount of additional collateral
Expand All @@ -113,6 +148,24 @@ contract SatoshiPeriphery is ISatoshiPeriphery, UUPSUpgradeable, OwnableUpgradea
IBorrowerOperationsFacet(xApp).addColl(troveManager, msg.sender, _collAmount, _upperHint, _lowerHint);
}

function addCollWithSupraPriceUpdate(
ITroveManager troveManager,
uint256 _collAmount,
address _upperHint,
address _lowerHint,
bytes calldata _bytesProof
)
external
{
IERC20 collateralToken = troveManager.collateralToken();

_updateSupraPriceFeed(troveManager, _bytesProof);

_beforeAddColl(collateralToken, _collAmount);

IBorrowerOperationsFacet(xApp).addColl(troveManager, msg.sender, _collAmount, _upperHint, _lowerHint);
}

/// @notice Withdraws _collWithdrawal of collateral from the caller’s Trove
/// @dev Executes only if the user has an active Trove,
/// @dev Withdrawal would not pull the user’s Trove below the MCR, and the resulting total collateralization ratio of the system is above 150%(TCR)
Expand All @@ -139,6 +192,28 @@ contract SatoshiPeriphery is ISatoshiPeriphery, UUPSUpgradeable, OwnableUpgradea
_afterWithdrawColl(collateralToken, userCollAmount);
}

function withdrawColl(
ITroveManager troveManager,
uint256 _collWithdrawal,
address _upperHint,
address _lowerHint,
bytes calldata _bytesProof
)
external
{
IERC20 collateralToken = troveManager.collateralToken();
uint256 collTokenBalanceBefore = collateralToken.balanceOf(address(this));

_updateSupraPriceFeed(troveManager, _bytesProof);

IBorrowerOperationsFacet(xApp).withdrawColl(troveManager, msg.sender, _collWithdrawal, _upperHint, _lowerHint);

uint256 collTokenBalanceAfter = collateralToken.balanceOf(address(this));
uint256 userCollAmount = collTokenBalanceAfter - collTokenBalanceBefore;
require(userCollAmount == _collWithdrawal, "SatoshiPeriphery: Collateral amount mismatch");
_afterWithdrawColl(collateralToken, userCollAmount);
}

/// @notice Issues _debtAmount of Debt token from the caller’s Trove to the caller.
/// @dev Executes only if the Trove's collateralization ratio would remain above the minimum
/// @param troveManager The TroveManager contract
Expand Down Expand Up @@ -168,6 +243,32 @@ contract SatoshiPeriphery is ISatoshiPeriphery, UUPSUpgradeable, OwnableUpgradea
_afterWithdrawDebt(userDebtAmount, _lzSendParam);
}

function withdrawDebtWithSupraPriceUpdate(
ITroveManager troveManager,
uint256 _maxFeePercentage,
uint256 _debtAmount,
address _upperHint,
address _lowerHint,
LzSendParam calldata _lzSendParam,
bytes calldata _bytesProof
)
external
payable
{
uint256 debtTokenBalanceBefore = debtToken.balanceOf(address(this));

_updateSupraPriceFeed(troveManager, _bytesProof);

IBorrowerOperationsFacet(xApp).withdrawDebt(
troveManager, msg.sender, _maxFeePercentage, _debtAmount, _upperHint, _lowerHint
);
uint256 debtTokenBalanceAfter = debtToken.balanceOf(address(this));
uint256 userDebtAmount = debtTokenBalanceAfter - debtTokenBalanceBefore;
require(userDebtAmount == _debtAmount, "SatoshiPeriphery: Debt amount mismatch");

_afterWithdrawDebt(userDebtAmount, _lzSendParam);
}

/// @notice Repays _debtAmount of Debt token to the caller’s Trove
/// @param troveManager The TroveManager contract
/// @param _debtAmount The amount of debt to repay
Expand All @@ -179,13 +280,26 @@ contract SatoshiPeriphery is ISatoshiPeriphery, UUPSUpgradeable, OwnableUpgradea
address _upperHint,
address _lowerHint
)
external
public
{
_beforeRepayDebt(_debtAmount);

IBorrowerOperationsFacet(xApp).repayDebt(troveManager, msg.sender, _debtAmount, _upperHint, _lowerHint);
}

function repayDebtWithSupraPriceUpdate(
ITroveManager troveManager,
uint256 _debtAmount,
address _upperHint,
address _lowerHint,
bytes calldata _bytesProof
)
external
{
_updateSupraPriceFeed(troveManager, _bytesProof);
repayDebt(troveManager, _debtAmount, _upperHint, _lowerHint);
}

/// @notice Enables a borrower to simultaneously change (decrease/increase) both their collateral and debt,
function adjustTrove(
ITroveManager troveManager,
Expand Down Expand Up @@ -239,6 +353,60 @@ contract SatoshiPeriphery is ISatoshiPeriphery, UUPSUpgradeable, OwnableUpgradea
}
}

function adjustTroveWithSupraPriceUpdate(
ITroveManager troveManager,
uint256 _maxFeePercentage,
uint256 _collDeposit,
uint256 _collWithdrawal,
uint256 _debtChange,
bool _isDebtIncrease,
address _upperHint,
address _lowerHint,
LzSendParam calldata _lzSendParam,
bytes calldata _bytesProof
)
external
payable
{
if (_collDeposit != 0 && _collWithdrawal != 0) revert CannotWithdrawAndAddColl();

IERC20 collateralToken = troveManager.collateralToken();
_updateSupraPriceFeed(troveManager, _bytesProof);
_beforeAddColl(collateralToken, _collDeposit);

uint256 debtTokenBalanceBefore = debtToken.balanceOf(address(this));

// repay debt
if (!_isDebtIncrease) {
_beforeRepayDebt(_debtChange);
}

IBorrowerOperationsFacet(xApp).adjustTrove(
troveManager,
msg.sender,
_maxFeePercentage,
_collDeposit,
_collWithdrawal,
_debtChange,
_isDebtIncrease,
_upperHint,
_lowerHint
);

uint256 debtTokenBalanceAfter = debtToken.balanceOf(address(this));
// withdraw collateral
_afterWithdrawColl(collateralToken, _collWithdrawal);

// withdraw debt
if (_isDebtIncrease) {
require(
debtTokenBalanceAfter - debtTokenBalanceBefore == _debtChange, "SatoshiPeriphery: Debt amount mismatch"
);

_afterWithdrawDebt(_debtChange, _lzSendParam);
}
}

/// @notice Close the trove from the caller
/// @param troveManager The TroveManager contract
function closeTrove(ITroveManager troveManager) external {
Expand All @@ -257,6 +425,23 @@ contract SatoshiPeriphery is ISatoshiPeriphery, UUPSUpgradeable, OwnableUpgradea
_afterWithdrawColl(collateralToken, userCollAmount);
}

function closeTroveWithSupraPriceUpdate(ITroveManager troveManager, bytes calldata _bytesProof) external {
(uint256 collAmount, uint256 debtAmount) = troveManager.getTroveCollAndDebt(msg.sender);
uint256 netDebtAmount = debtAmount - ICoreFacet(xApp).gasCompensation();
_updateSupraPriceFeed(troveManager, _bytesProof);
_beforeRepayDebt(netDebtAmount);

IERC20 collateralToken = troveManager.collateralToken();
uint256 collTokenBalanceBefore = collateralToken.balanceOf(address(this));

IBorrowerOperationsFacet(xApp).closeTrove(troveManager, msg.sender);

uint256 collTokenBalanceAfter = collateralToken.balanceOf(address(this));
uint256 userCollAmount = collTokenBalanceAfter - collTokenBalanceBefore;
require(userCollAmount == collAmount, "SatoshiPeriphery: Collateral amount mismatch");
_afterWithdrawColl(collateralToken, userCollAmount);
}

function liquidateTroves(
ITroveManager troveManager,
uint256 maxTrovesToLiquidate,
Expand All @@ -281,6 +466,33 @@ contract SatoshiPeriphery is ISatoshiPeriphery, UUPSUpgradeable, OwnableUpgradea
_afterWithdrawColl(troveManager.collateralToken(), userCollAmount);
}

function liquidateTrovesWithSupraPriceUpdate(
ITroveManager troveManager,
uint256 maxTrovesToLiquidate,
uint256 maxICR,
LzSendParam calldata _lzSendParam,
bytes calldata _bytesProof
)
external
payable
{
uint256 debtTokenBalanceBefore = debtToken.balanceOf(address(this));
uint256 collTokenBalanceBefore = troveManager.collateralToken().balanceOf(address(this));

_updateSupraPriceFeed(troveManager, _bytesProof);

ILiquidationFacet(xApp).liquidateTroves(troveManager, maxTrovesToLiquidate, maxICR);

uint256 debtTokenBalanceAfter = debtToken.balanceOf(address(this));
uint256 collTokenBalanceAfter = troveManager.collateralToken().balanceOf(address(this));

uint256 userDebtAmount = debtTokenBalanceAfter - debtTokenBalanceBefore;
uint256 userCollAmount = collTokenBalanceAfter - collTokenBalanceBefore;

_afterWithdrawDebt(userDebtAmount, _lzSendParam);
_afterWithdrawColl(troveManager.collateralToken(), userCollAmount);
}

// INTERNAL FUNCTIONS //

/// @dev Only support ERC20 token, not support native token
Expand Down Expand Up @@ -342,6 +554,12 @@ contract SatoshiPeriphery is ISatoshiPeriphery, UUPSUpgradeable, OwnableUpgradea
debtToken.safeTransferFrom(msg.sender, address(this), debtAmount);
}

function _updateSupraPriceFeed(ITroveManager troveManager, bytes calldata _bytesProof) internal {
(IPriceFeed priceFeed,) = IPriceFeedAggregatorFacet(xApp).oracleRecords(troveManager.collateralToken());
ISupraOraclePull supra_pull = ISupraOraclePull(priceFeed.source());
supra_pull.verifyOracleProof(_bytesProof);
}

/// @notice Override the _authorizeUpgrade function inherited from UUPSUpgradeable contract
// solhint-disable-next-line no-empty-blocks
function _authorizeUpgrade(address newImplementation) internal view override onlyOwner {
Expand Down