Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tlc delegatecall #807

Merged
merged 2 commits into from
May 29, 2023
Merged
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
5 changes: 0 additions & 5 deletions protocol/contracts/common/SafeCast.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ library SafeCast {
if (downcasted != amount) revert Overflow(amount);
}

function encodeUInt216(uint256 amount) internal pure returns (uint216 downcasted) {
downcasted = uint216(amount);
if (downcasted != amount) revert Overflow(amount);
}

function encodeUInt80(uint256 amount) internal pure returns (uint80 downcasted) {
downcasted = uint80(amount);
if (downcasted != amount) revert Overflow(amount);
Expand Down
9 changes: 9 additions & 0 deletions protocol/contracts/interfaces/v2/ITreasuryReservesVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { ITempleDebtToken } from "contracts/interfaces/v2/ITempleDebtToken.sol";
import { ITempleStrategy, ITempleBaseStrategy } from "contracts/interfaces/v2/strategies/ITempleBaseStrategy.sol";
import { ITempleElevatedAccess } from "contracts/interfaces/v2/access/ITempleElevatedAccess.sol";
import { IMintableToken } from "contracts/interfaces/common/IMintableToken.sol";

/**
* @title Treasury Reserves Vault (TRV)
Expand All @@ -32,6 +33,7 @@ interface ITreasuryReservesVault is ITempleElevatedAccess {

event Borrow(address indexed strategy, address indexed recipient, uint256 stablesAmount);
event Repay(address indexed strategy, address indexed from, uint256 stablesAmount);
// event RepayTemple(address indexed strategy, address indexed from, uint256 templeBurned, uint256 debtBurned);
event RealisedGain(address indexed strategy, uint256 amount);
event RealisedLoss(address indexed strategy, uint256 amount);
event TreasuryPriceIndexSet(uint256 oldTpi, uint256 newTpi);
Expand Down Expand Up @@ -135,6 +137,11 @@ interface ITreasuryReservesVault is ITempleElevatedAccess {
*/
function apiVersion() external pure returns (string memory);

/**
* @notice The address of the Temple token.
*/
function templeToken() external view returns (IMintableToken);

/**
* @notice The address of the stable token (eg DAI) used to value all strategy's assets and debt.
*/
Expand Down Expand Up @@ -256,6 +263,8 @@ interface ITreasuryReservesVault is ITempleElevatedAccess {
*/
function repayAll(address strategy) external returns (uint256 amountRepaid);

function repayTemple(uint256 repayAmount, address strategy) external;

/**
* @notice The second step in a two-phase shutdown. A strategy (automated) or executor (manual) calls
* to effect the shutdown. isShuttingDown must be true for the strategy first.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,48 @@ pragma solidity ^0.8.17;
// Temple (interfaces/v2/templeLineOfCredit/ITempleLineOfCredit.sol)

import { ITlcDataTypes } from "contracts/interfaces/v2/templeLineOfCredit/ITlcDataTypes.sol";
import { ITlcEventsAndErrors } from "contracts/interfaces/v2/templeLineOfCredit/ITlcEventsAndErrors.sol";

interface ITempleLineOfCredit is ITlcDataTypes {
error InsufficentCollateral(uint256 maxCapacity, uint256 borrowAmount);
error ExceededBorrowedAmount(uint256 totalDebtAmount, uint256 repayAmount);
interface ITempleLineOfCredit is ITlcDataTypes, ITlcEventsAndErrors {
/** Add Collateral */
function addCollateral(uint256 collateralAmount, address onBehalfOf) external;

event PostCollateral(address indexed fundedBy, address indexed onBehalfOf, uint256 collateralAmount);
event Borrow(address indexed account, address indexed recipient, address indexed token, uint256 amount);
event Repay(address indexed fundedBy, address indexed onBehalfOf, address indexed token, uint256 repayAmount);
/** Remove Collateral (requires a request with cooldown first) */
function requestRemoveCollateral(uint256 amount) external;
function cancelRemoveCollateralRequest(address account) external;
function removeCollateral(address recipient) external;

// @todo add all functions, then add override in TempleLineOfCredit
/** Borrow (requires a request with cooldown first) */
function requestBorrow(TokenType tokenType, uint256 amount) external;
function cancelBorrowRequest(address account, TokenType tokenType) external;
function borrow(TokenType tokenType, address recipient) external;

/** Repay */
function repay(TokenType tokenType, uint256 repayAmount, address onBehalfOf) external;
function repayAll(TokenType tokenType, address onBehalfOf) external;

/** Position views */
function userPosition(address account) external view returns (UserPosition memory position);
function totalPosition() external view returns (TotalPosition[2] memory positions);
function getUserData(address account) external view returns (UserData memory);
function getReserveToken(TokenType tokenType) external view returns (ReserveToken memory);
function getReserveCache(TokenType tokenType) external view returns (ReserveCache memory);

/** Liquidations */
function computeLiquidity(
address[] memory accounts,
bool includePendingRequests
) external view returns (LiquidityStatus[] memory status);
function batchLiquidate(address[] memory accounts) external;

// Manually checkpoint debt to adjust interest rate based on latest utillization ratio
function refreshInterestRates(TokenType tokenType) external;

/** EXECUTORS/RESCUERS ONLY */
function setTlcStrategy(address _tlcStrategy) external;
function setWithdrawCollateralCooldownSecs(uint256 cooldownSecs) external;
function setBorrowCooldownSecs(TokenType tokenType, uint256 cooldownSecs) external;
function setInterestRateModel(TokenType tokenType, address interestRateModel) external;
function setMaxLtvRatio(TokenType tokenType, uint256 maxLtvRatio) external;
function recoverToken(address token, address to, uint256 amount) external;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,55 @@ import { IInterestRateModel } from "contracts/interfaces/v2/interestRate/IIntere
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface ITlcDataTypes {
struct UserDebtPosition {
uint256 debt;
uint256 maxBorrow;
uint256 healthFactor;
uint256 loanToValueRatio;
}

struct UserPosition {
uint256 collateralPosted;
UserDebtPosition[2] debtPositions;
}

struct TotalPosition {
/// @notice The DAI utilization rate as of the last checkpoint
uint256 utilizationRatio;

// @notice The DAI borrow interest rate as of the last checkpoint
int256 borrowRate;

// @notice The DAI total debt across all users as of this block
uint256 totalDebt;
}






enum ModuleKind {
LIQUIDATION,
POSITION
}

enum TokenType {
DAI,
OUD
}

// enum FundsRequestType {
// BORROW_DAI,
// BORROW_OUD,
// WITHDRAW_COLLATERAL
// }

struct WithdrawFundsRequest {
uint128 amount;
uint32 requestedAt;
}

enum TokenPriceType {
/// @notice equal to 1 USD
STABLE,
Expand All @@ -22,8 +71,9 @@ interface ITlcDataTypes {
TRV_UTILIZATION_RATE
}

// @todo byte pack all of these
struct ReserveTokenConfig {
address tokenAddress;

/// @notice The type of how to lookup the price of the token
TokenPriceType tokenPriceType;

Expand All @@ -34,10 +84,11 @@ interface ITlcDataTypes {
IInterestRateModel interestRateModel;

/// @notice Maximum Loan To Value (LTV) ratio to prevent liquidation
uint216 maxLtvRatio;
uint128 maxLtvRatio;

uint32 borrowCooldownSecs;
}

// @todo byte pack all of these
struct ReserveTokenTotals {
// Packed slot: 32 + 128 + 96 = 256

Expand All @@ -60,19 +111,30 @@ interface ITlcDataTypes {

struct UserTokenDebt {
uint128 debt;
WithdrawFundsRequest borrowRequest;
uint128 interestAccumulator;
}

struct UserData {
uint256 collateralPosted;
mapping(IERC20 => UserTokenDebt) debtData;
WithdrawFundsRequest removeCollateralRequest;
UserTokenDebt[2] debtData;
}

struct LiquidityStatus {
// True if either DAI or OUD has exceeded the max LTV
bool hasExceededMaxLtv;

uint256 collateral;
uint256[2] debt;
}

// @todo check if all of these are actually used
struct ReserveCache {
// @todo rename to totalDebt?
ReserveTokenConfig config;

/// @notice The last time the debt was updated for this token
uint32 interestAccumulatorUpdatedAt;
// uint32 interestAccumulatorUpdatedAt;

/// @notice Total amount that has already been borrowed, which increases as interest accrues
uint128 totalDebt;
Expand All @@ -83,16 +145,7 @@ interface ITlcDataTypes {
uint128 interestAccumulator;

uint256 price;

/// @notice The type of interest rate model used for this token
InterestRateModelType interestRateModelType;

/// @notice The interest rate model contract
IInterestRateModel interestRateModel;

/// @notice Maximum Loan To Value (LTV) ratio to prevent liquidation
uint216 maxLtvRatio;


/// @notice The max allowed to be borrowed from the TRV
/// @dev Used as the denominator in the Utilisation Ratio
uint256 trvDebtCeiling;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
pragma solidity ^0.8.17;
// SPDX-License-Identifier: AGPL-3.0-or-later
// Temple (interfaces/v2/templeLineOfCredit/ITempleLineOfCredit.sol)

import { ITlcDataTypes } from "contracts/interfaces/v2/templeLineOfCredit/ITlcDataTypes.sol";

interface ITlcEventsAndErrors {
error ExceededMaxLtv();
error UnknownFailure();

error ExceededBorrowedAmount(address token, uint256 totalDebtAmount, uint256 repayAmount);
error CooldownPeriodNotMet(uint32 requestedAt, uint32 cooldownSecs);

event TlcStrategySet(address indexed strategy);
event WithdrawCollateralCooldownSecsSet(uint256 cooldownSecs);
event BorrowCooldownSecsSet(ITlcDataTypes.TokenType tokenType, uint256 cooldownSecs);

event CollateralAdded(address indexed fundedBy, address indexed onBehalfOf, uint256 collateralAmount);
event CollateralRemoved(address indexed account, address indexed recipient, uint256 collateralAmount);

event RemoveCollateralRequested(address indexed account, uint256 amount);
event RemoveCollateralRequestCancelled(address indexed account);

event BorrowRequested(address indexed account, ITlcDataTypes.TokenType tokenType, uint256 amount);
event BorrowRequestCancelled(address indexed account, ITlcDataTypes.TokenType tokenType);
event Borrow(address indexed account, address indexed recipient, ITlcDataTypes.TokenType tokenType, uint256 amount);

event Repay(address indexed fundedBy, address indexed onBehalfOf, ITlcDataTypes.TokenType tokenType, uint256 repayAmount);

event Liquidated(address indexed account, address indexed unhealthyDebtToken, uint256 healthFactor, uint256 debtAmount, uint256 collateralSeized);

event InterestRateUpdate(address indexed token, int96 newInterestRate);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// pragma solidity ^0.8.17;
// // SPDX-License-Identifier: AGPL-3.0-or-later
// // Temple (interfaces/v2/templeLineOfCredit/ITempleLineOfCredit.sol)

// import { ITlcDataTypes } from "contracts/interfaces/v2/templeLineOfCredit/ITlcDataTypes.sol";

// interface ITlcPositionHelper is ITlcDataTypes {

// struct UserDebtPosition {
// uint256 debt;
// uint256 maxBorrow;
// uint256 healthFactor;
// uint256 loanToValueRatio;
// }

// struct UserPosition {
// uint256 collateralPosted;
// UserDebtPosition[2] debtPositions;
// }

// struct TotalPosition {
// /// @notice The DAI utilization rate as of the last checkpoint
// uint256 utilizationRatio;

// // @notice The DAI borrow interest rate as of the last checkpoint
// int256 borrowRate;

// // @notice The DAI total debt across all users as of this block
// uint256 totalDebt;
// }
// }
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pragma solidity ^0.8.17;
// SPDX-License-Identifier: AGPL-3.0-or-later
// Temple (interfaces/v2/tlc/ITlcStrategy.sol)

import { ITempleStrategy } from "contracts/interfaces/v2/strategies/ITempleStrategy.sol";

interface ITlcStrategy is ITempleStrategy {
function fundFromTrv(uint256 amount, address recipient) external;
}
9 changes: 5 additions & 4 deletions protocol/contracts/v2/TempleDebtToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,12 @@ contract TempleDebtToken is ITempleDebtToken, TempleElevatedAccess {
// Check the user isn't paying off more debt than they have
uint256 _debtorBalance = _balanceOf(debtor, _totalPrincipalAndBase);
if (_burnAmount > _debtorBalance) {
if (_capBurnAmount) {
// @todo this looks like it's always set to true? need to recheck this.
// if (_capBurnAmount) {
_burnAmount = _debtorBalance;
} else {
revert BurnExceedsBalance(_balanceOf(debtor, _totalPrincipalAndBase), _burnAmount);
}
// } else {
// revert BurnExceedsBalance(_balanceOf(debtor, _totalPrincipalAndBase), _burnAmount);
// }
}
}

Expand Down
Loading