Skip to content
Open
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
212 changes: 210 additions & 2 deletions src/core/helpers/SatoshiPeriphery.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import { ICoreFacet } from "../interfaces/ICoreFacet.sol";
import { ILiquidationFacet } from "../interfaces/ILiquidationFacet.sol";
import { ITroveManager } from "../interfaces/ITroveManager.sol";

import { ISupraOraclePull } from "../../priceFeed/interfaces/ISupraOraclePull.sol";
import { IDebtToken } from "../interfaces/IDebtToken.sol";
import { IPriceFeedAggregatorFacet } from "../interfaces/IPriceFeedAggregatorFacet.sol";
import { ISatoshiPeriphery, LzSendParam } from "./interfaces/ISatoshiPeriphery.sol";
import { IWETH } from "./interfaces/IWETH.sol";
import {
Expand Down Expand Up @@ -92,21 +94,63 @@ 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
/// @param _upperHint The upper hint (for querying the position of the sorted trove)
/// @param _lowerHint The lower hint (for querying the position of the sorted trove)
function addColl(
function addColl(ITroveManager troveManager, uint256 _collAmount, address _upperHint, address _lowerHint) external {
IERC20 collateralToken = troveManager.collateralToken();

_beforeAddColl(collateralToken, _collAmount);

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

function addCollWithSupraPriceUpdate(
ITroveManager troveManager,
uint256 _collAmount,
address _upperHint,
address _lowerHint
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);
Expand Down Expand Up @@ -138,6 +182,28 @@ contract SatoshiPeriphery is ISatoshiPeriphery, UUPSUpgradeable, OwnableUpgradea
_afterWithdrawColl(collateralToken, userCollAmount);
}

function withdrawCollWithSupraPriceUpdate(
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 @@ -166,6 +232,29 @@ 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 @@ -184,6 +273,21 @@ contract SatoshiPeriphery is ISatoshiPeriphery, UUPSUpgradeable, OwnableUpgradea
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);
_beforeRepayDebt(_debtAmount);

IBorrowerOperationsFacet(xApp).repayDebt(troveManager, msg.sender, _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 @@ -238,6 +342,61 @@ 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 @@ -256,6 +415,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 @@ -280,6 +456,32 @@ 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 @@ -346,4 +548,10 @@ contract SatoshiPeriphery is ISatoshiPeriphery, UUPSUpgradeable, OwnableUpgradea
function _authorizeUpgrade(address newImplementation) internal view override onlyOwner {
// No additional authorization logic is needed for this contract
}

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);
}
}