Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"src/proposals/ConvertibleDepositActivator.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.20;
// Libraries
import {Owned} from "@solmate-6.2.0/auth/Owned.sol";
// Interfaces
import {IERC20} from "src/interfaces/IERC20.sol";
import {IERC4626} from "src/interfaces/IERC4626.sol";
import {IDepositManager} from "src/policies/interfaces/deposits/IDepositManager.sol";
import {IDepositRedemptionVault} from "src/policies/interfaces/deposits/IDepositRedemptionVault.sol";
import {IDepositFacility} from "src/policies/interfaces/deposits/IDepositFacility.sol";
import {IConvertibleDepositAuctioneer} from "src/policies/interfaces/deposits/IConvertibleDepositAuctioneer.sol";
import {IEmissionManager} from "src/policies/interfaces/IEmissionManager.sol";
import {IPeriodicTaskManager} from "src/bases/interfaces/IPeriodicTaskManager.sol";
import {IReserveMigrator} from "src/policies/interfaces/IReserveMigrator.sol";
import {IOperator} from "src/policies/interfaces/IOperator.sol";
import {IYieldRepo} from "src/policies/interfaces/IYieldRepo.sol";
import {IEnabler} from "src/periphery/interfaces/IEnabler.sol";
/// @notice Single-use contract to activate the Convertible Deposits system
contract ConvertibleDepositActivator is Owned {
// Existing contracts
address public constant RESERVE_MIGRATOR = 0x986b99579BEc7B990331474b66CcDB94Fa2419F5;
address public constant OPERATOR = 0x6417F206a0a6628Da136C0Faa39026d0134D2b52;
address public constant YIELD_REPURCHASE_FACILITY = 0x271e35a8555a62F6bA76508E85dfD76D580B0692;
// New contracts
address public immutable DEPOSIT_MANAGER;
address public immutable CD_FACILITY;
address public immutable REDEMPTION_VAULT;
address public immutable CD_AUCTIONEER;
address public immutable EMISSION_MANAGER;
address public immutable HEART;
address public immutable RESERVE_WRAPPER;
string public constant CD_NAME = "cdf";
// Tokens
address public constant USDS = 0xdC035D45d973E3EC169d2276DDab16f1e407384F;
address public constant SUSDS = 0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD;
// Asset configuration
uint256 public constant USDS_MAX_CAPACITY = 1_000_000e18; // 1M USDS
uint256 public constant USDS_MIN_DEPOSIT = 1e18; // 1 USDS
// Deposit periods (in months)
uint8 public constant PERIOD_1M = 1;
uint8 public constant PERIOD_2M = 2;
uint8 public constant PERIOD_3M = 3;
// Reclaim rate (in basis points)
uint16 public constant RECLAIM_RATE = 90e2; // 90%
// ConvertibleDepositAuctioneer initial parameters
uint256 public constant CDA_INITIAL_TARGET = 0;
uint256 public constant CDA_INITIAL_TICK_SIZE = 0;
uint256 public constant CDA_INITIAL_MIN_PRICE = 0;
uint256 public constant CDA_INITIAL_TICK_SIZE_BASE = 2e18; // 2.0
uint24 public constant CDA_INITIAL_TICK_STEP_MULTIPLIER = 10075; // 0.75% increase
uint8 public constant CDA_AUCTION_TRACKING_PERIOD = 7; // 7 days
uint256 public constant CDA_MINIMUM_BID = 100e18; // 100 USDS
// EmissionManager parameters
uint256 public constant EM_BASE_EMISSIONS_RATE = 200000; // 0.02%/day
uint256 public constant EM_MINIMUM_PREMIUM = 1e18; // 100% premium
uint256 public constant EM_BACKING = 11690000000000000000; // 11.69 USDS/OHM
uint256 public constant EM_TICK_SIZE = 150e9; // 150 OHM
uint256 public constant EM_MIN_PRICE_SCALAR = 12e17; // 120% min price multiplier
uint256 public constant EM_BOND_MARKET_CAPACITY_SCALAR = 1e18; // 100% bond market capacity scalar
uint48 public constant EM_RESTART_TIMEFRAME = 950400; // 11 days
/// @notice True if the activation has been performed
bool public isActivated = false;
event Activated(address caller);
error AlreadyActivated();
error InvalidParams(string reason);
constructor(
address owner_,
address depositManager_,
address cdFacility_,
address cdAuctioneer_,
address redemptionVault_,
address emissionManager_,
address heart_,
address reserveWrapper_
) Owned(owner_) {
if (owner_ == address(0)) revert InvalidParams("owner");
if (depositManager_ == address(0)) revert InvalidParams("depositManager");
if (cdFacility_ == address(0)) revert InvalidParams("cdFacility");
if (cdAuctioneer_ == address(0)) revert InvalidParams("cdAuctioneer");
if (redemptionVault_ == address(0)) revert InvalidParams("redemptionVault");
if (emissionManager_ == address(0)) revert InvalidParams("emissionManager");
if (heart_ == address(0)) revert InvalidParams("heart");
if (reserveWrapper_ == address(0)) revert InvalidParams("reserveWrapper");
DEPOSIT_MANAGER = depositManager_;
CD_FACILITY = cdFacility_;
CD_AUCTIONEER = cdAuctioneer_;
REDEMPTION_VAULT = redemptionVault_;
EMISSION_MANAGER = emissionManager_;
HEART = heart_;
RESERVE_WRAPPER = reserveWrapper_;
}
function _activateContracts() internal {
// 1. Enable DepositManager contract
IEnabler(DEPOSIT_MANAGER).enable("");
// 2. Set operator name on DepositManager for ConvertibleDepositFacility
IDepositManager(DEPOSIT_MANAGER).setOperatorName(CD_FACILITY, CD_NAME);
// 3. Enable ConvertibleDepositFacility contract
IEnabler(CD_FACILITY).enable("");
// 6. Authorize ConvertibleDepositFacility in DepositRedemptionVault
IDepositRedemptionVault(REDEMPTION_VAULT).authorizeFacility(CD_FACILITY);
// 7. Authorize DepositRedemptionVault in ConvertibleDepositFacility
IDepositFacility(CD_FACILITY).authorizeOperator(REDEMPTION_VAULT);
// 8. Enable DepositRedemptionVault
IEnabler(REDEMPTION_VAULT).enable("");
}
function _configureAssets() internal {
IDepositManager depositManager = IDepositManager(DEPOSIT_MANAGER);
IERC20 usds = IERC20(USDS);
// 1. Configure USDS in DepositManager
depositManager.addAsset(usds, IERC4626(SUSDS), USDS_MAX_CAPACITY, USDS_MIN_DEPOSIT);
// 2. Add USDS-1m/2m/3m to DepositManager
depositManager.addAssetPeriod(usds, PERIOD_1M, CD_FACILITY);
depositManager.addAssetPeriod(usds, PERIOD_2M, CD_FACILITY);
depositManager.addAssetPeriod(usds, PERIOD_3M, CD_FACILITY);
// 3. Set reclaim rates on ConvertibleDepositFacility
IDepositFacility(CD_FACILITY).setAssetPeriodReclaimRate(usds, PERIOD_1M, RECLAIM_RATE);
IDepositFacility(CD_FACILITY).setAssetPeriodReclaimRate(usds, PERIOD_2M, RECLAIM_RATE);
IDepositFacility(CD_FACILITY).setAssetPeriodReclaimRate(usds, PERIOD_3M, RECLAIM_RATE);
}
function _configureAuction() internal {
IConvertibleDepositAuctioneer cdAuctioneer = IConvertibleDepositAuctioneer(CD_AUCTIONEER);
// 1. Enable USDS-1m/2m/3m in ConvertibleDepositAuctioneer
cdAuctioneer.enableDepositPeriod(PERIOD_1M);
cdAuctioneer.enableDepositPeriod(PERIOD_2M);
cdAuctioneer.enableDepositPeriod(PERIOD_3M);
// 2. Set minimum bid on ConvertibleDepositAuctioneer
cdAuctioneer.setMinimumBid(CDA_MINIMUM_BID);
// 3. Enable ConvertibleDepositAuctioneer (with disabled auction)
bytes memory auctioneerParams = abi.encode(
IConvertibleDepositAuctioneer.EnableParams({
target: CDA_INITIAL_TARGET,
tickSize: CDA_INITIAL_TICK_SIZE,
minPrice: CDA_INITIAL_MIN_PRICE,
tickSizeBase: CDA_INITIAL_TICK_SIZE_BASE,
tickStep: CDA_INITIAL_TICK_STEP_MULTIPLIER,
auctionTrackingPeriod: CDA_AUCTION_TRACKING_PERIOD
})
);
IEnabler(CD_AUCTIONEER).enable(auctioneerParams);
// 4. Enable EmissionManager
bytes memory emissionParams = abi.encode(
IEmissionManager.EnableParams({
baseEmissionsRate: EM_BASE_EMISSIONS_RATE,
minimumPremium: EM_MINIMUM_PREMIUM,
backing: EM_BACKING,
tickSize: EM_TICK_SIZE,
minPriceScalar: EM_MIN_PRICE_SCALAR,
bondMarketCapacityScalar: EM_BOND_MARKET_CAPACITY_SCALAR,
restartTimeframe: EM_RESTART_TIMEFRAME
})
);
IEnabler(EMISSION_MANAGER).enable(emissionParams);
}
function _configurePeriodicTasks() internal {
IPeriodicTaskManager taskManager = IPeriodicTaskManager(HEART);
// 1. Enable ReserveWrapper
IEnabler(RESERVE_WRAPPER).enable("");
// 2. Add ConvertibleDepositFacility to periodic tasks
// This is done before the ReserveMigrator and ReserveWrapper,
// so that any yield is converted into the correct asset
taskManager.addPeriodicTask(CD_FACILITY);
// 3. Add ReserveMigrator.migrate() to periodic tasks
taskManager.addPeriodicTaskAtIndex(
RESERVE_MIGRATOR,
IReserveMigrator.migrate.selector,
1 // Second task
);
// 4. Add ReserveWrapper to periodic tasks
taskManager.addPeriodicTask(RESERVE_WRAPPER);
// 5. Add Operator.operate() to periodic tasks
taskManager.addPeriodicTaskAtIndex(
OPERATOR,
IOperator.operate.selector,
3 // Fourth task
);
// 6. Add YieldRepurchaseFacility.endEpoch() to periodic tasks
// Tasks 2-4 are run before YRF, so that yield is properly calculated
taskManager.addPeriodicTaskAtIndex(
YIELD_REPURCHASE_FACILITY,
IYieldRepo.endEpoch.selector,
4 // Fifth task
);
// 7. Add EmissionManager to periodic tasks
taskManager.addPeriodicTask(EMISSION_MANAGER);
// 8. Enable Heart
IEnabler(HEART).enable("");
}
/// @notice Activates the Convertible Deposits system
/// @dev This function assumes:
/// - The "admin" role has been granted to the contract
///
/// This function reverts if:
/// - The caller is not the owner
/// - The function has already been run
function activate() external onlyOwner {
// Revert if already activated
if (isActivated) revert AlreadyActivated();
_activateContracts();
_configureAssets();
_configureAuction();
_configurePeriodicTasks();
// Mark as activated
isActivated = true;
emit Activated(msg.sender);
}
}
"
},
"dependencies/solmate-6.2.0/src/auth/Owned.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event OwnershipTransferred(address indexed user, address indexed newOwner);
/*//////////////////////////////////////////////////////////////
OWNERSHIP STORAGE
//////////////////////////////////////////////////////////////*/
address public owner;
modifier onlyOwner() virtual {
require(msg.sender == owner, "UNAUTHORIZED");
_;
}
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(address _owner) {
owner = _owner;
emit OwnershipTransferred(address(0), _owner);
}
/*//////////////////////////////////////////////////////////////
OWNERSHIP LOGIC
//////////////////////////////////////////////////////////////*/
function transferOwnership(address newOwner) public virtual onlyOwner {
owner = newOwner;
emit OwnershipTransferred(msg.sender, newOwner);
}
}
"
},
"src/interfaces/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
// Imported from forge-std
/// @dev Interface of the ERC20 standard as defined in the EIP.
/// @dev This includes the optional name, symbol, and decimals metadata.
interface IERC20 {
/// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`).
event Transfer(address indexed from, address indexed to, uint256 value);
/// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value`
/// is the new allowance.
event Approval(address indexed owner, address indexed spender, uint256 value);
/// @notice Returns the amount of tokens in existence.
function totalSupply() external view returns (uint256);
/// @notice Returns the amount of tokens owned by `account`.
function balanceOf(address account) external view returns (uint256);
/// @notice Moves `amount` tokens from the caller's account to `to`.
function transfer(address to, uint256 amount) external returns (bool);
/// @notice Returns the remaining number of tokens that `spender` is allowed
/// to spend on behalf of `owner`
function allowance(address owner, address spender) external view returns (uint256);
/// @notice Sets `amount` as the allowance of `spender` over the caller's tokens.
/// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
function approve(address spender, uint256 amount) external returns (bool);
/// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism.
/// `amount` is then deducted from the caller's allowance.
function transferFrom(address from, address to, uint256 amount) external returns (bool);
/// @notice Returns the name of the token.
function name() external view returns (string memory);
/// @notice Returns the symbol of the token.
function symbol() external view returns (string memory);
/// @notice Returns the decimals places of the token.
function decimals() external view returns (uint8);
}
"
},
"src/interfaces/IERC4626.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import {IERC20} from "./IERC20.sol";
// Imported from forge-std
/// @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in
/// https://eips.ethereum.org/EIPS/eip-4626
interface IERC4626 is IERC20 {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/// @notice Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
/// @dev
/// - MUST be an ERC-20 token contract.
/// - MUST NOT revert.
function asset() external view returns (address assetTokenAddress);
/// @notice Returns the total amount of the underlying asset that is “managed” by Vault.
/// @dev
/// - SHOULD include any compounding that occurs from yield.
/// - MUST be inclusive of any fees that are charged against assets in the Vault.
/// - MUST NOT revert.
function totalAssets() external view returns (uint256 totalManagedAssets);
/// @notice Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
/// scenario where all the conditions are met.
/// @dev
/// - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
/// - MUST NOT show any variations depending on the caller.
/// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
/// - MUST NOT revert.
///
/// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
/// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
/// from.
function convertToShares(uint256 assets) external view returns (uint256 shares);
/// @notice Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
/// scenario where all the conditions are met.
/// @dev
/// - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
/// - MUST NOT show any variations depending on the caller.
/// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
/// - MUST NOT revert.
///
/// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
/// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
/// from.
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/// @notice Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
/// through a deposit call.
/// @dev
/// - MUST return a limited value if receiver is subject to some deposit limit.
/// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
/// - MUST NOT revert.
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/// @notice Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
/// current on-chain conditions.
/// @dev
/// - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
/// call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
/// in the same transaction.
/// - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
/// deposit would be accepted, regardless if the user has enough tokens approved, etc.
/// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
/// - MUST NOT revert.
///
/// NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
/// share price or some other type of condition, meaning the depositor will lose assets by depositing.
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/// @notice Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
/// @dev
/// - MUST emit the Deposit event.
/// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
/// deposit execution, and are accounted for during deposit.
/// - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
/// approving enough underlying tokens to the Vault contract, etc).
///
/// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/// @notice Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
/// @dev
/// - MUST return a limited value if receiver is subject to some mint limit.
/// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
/// - MUST NOT revert.
function maxMint(address receiver) external view returns (uint256 maxShares);
/// @notice Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
/// current on-chain conditions.
/// @dev
/// - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
/// in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
/// same transaction.
/// - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
/// would be accepted, regardless if the user has enough tokens approved, etc.
/// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
/// - MUST NOT revert.
///
/// NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
/// share price or some other type of condition, meaning the depositor will lose assets by minting.
function previewMint(uint256 shares) external view returns (uint256 assets);
/// @notice Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
/// @dev
/// - MUST emit the Deposit event.
/// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
/// execution, and are accounted for during mint.
/// - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
/// approving enough underlying tokens to the Vault contract, etc).
///
/// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/// @notice Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
/// Vault, through a withdraw call.
/// @dev
/// - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
/// - MUST NOT revert.
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/// @notice Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
/// given current on-chain conditions.
/// @dev
/// - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
/// call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
/// called
/// in the same transaction.
/// - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
/// the withdrawal would be accepted, regardless if the user has enough shares, etc.
/// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
/// - MUST NOT revert.
///
/// NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
/// share price or some other type of condition, meaning the depositor will lose assets by depositing.
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/// @notice Burns shares from owner and sends exactly assets of underlying tokens to receiver.
/// @dev
/// - MUST emit the Withdraw event.
/// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
/// withdraw execution, and are accounted for during withdraw.
/// - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
/// not having enough shares, etc).
///
/// Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
/// Those methods should be performed separately.
function withdraw(
uint256 assets,
address receiver,
address owner
) external returns (uint256 shares);
/// @notice Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
/// through a redeem call.
/// @dev
/// - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
/// - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
/// - MUST NOT revert.
function maxRedeem(address owner) external view returns (uint256 maxShares);
/// @notice Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
/// given current on-chain conditions.
/// @dev
/// - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
/// in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
/// same transaction.
/// - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
/// redemption would be accepted, regardless if the user has enough shares, etc.
/// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
/// - MUST NOT revert.
///
/// NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
/// share price or some other type of condition, meaning the depositor will lose assets by redeeming.
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/// @notice Burns exactly shares from owner and sends assets of underlying tokens to receiver.
/// @dev
/// - MUST emit the Withdraw event.
/// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
/// redeem execution, and are accounted for during redeem.
/// - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
/// not having enough shares, etc).
///
/// NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
/// Those methods should be performed separately.
function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
}
"
},
"src/policies/interfaces/deposits/IDepositManager.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import {IERC20} from "src/interfaces/IERC20.sol";
import {IERC4626} from "src/interfaces/IERC4626.sol";
import {IAssetManager} from "src/bases/interfaces/IAssetManager.sol";
import {IReceiptTokenManager} from "src/policies/interfaces/deposits/IReceiptTokenManager.sol";
/// @title Deposit Manager
/// @notice Defines an interface for a policy that manages deposits on behalf of other contracts. It is meant to be used by the facilities, and is not an end-user policy.
///
/// Key terms for the contract:
/// - Asset: an ERC20 asset that can be deposited into the contract
/// - Asset vault: an optional ERC4626 vault that assets are deposited into
/// - Asset period: the combination of an asset and deposit period
interface IDepositManager is IAssetManager {
// ========== EVENTS ========== //
event OperatorYieldClaimed(
address indexed asset,
address indexed depositor,
address indexed operator,
uint256 amount
);
// Asset Configuration Events
event OperatorNameSet(address indexed operator, string name);
event AssetPeriodConfigured(
uint256 indexed receiptTokenId,
address indexed asset,
address indexed operator,
uint8 depositPeriod
);
event AssetPeriodEnabled(
uint256 indexed receiptTokenId,
address indexed asset,
address indexed operator,
uint8 depositPeriod
);
event AssetPeriodDisabled(
uint256 indexed receiptTokenId,
address indexed asset,
address indexed operator,
uint8 depositPeriod
);
event TokenRescued(address indexed token, uint256 amount);
// Borrowing Events
event BorrowingWithdrawal(
address indexed asset,
address indexed operator,
address indexed recipient,
uint256 amount
);
event BorrowingRepayment(
address indexed asset,
address indexed operator,
address indexed payer,
uint256 amount
);
event BorrowingDefault(
address indexed asset,
address indexed operator,
address indexed payer,
uint256 amount
);
// ========== ERRORS ========== //
error DepositManager_InvalidParams(string reason);
/// @notice Error if the action would leave the contract insolvent (liabilities > assets + borrowed)
///
/// @param asset The address of the underlying asset
/// @param requiredAssets The quantity of asset liabilities
/// @param depositedSharesInAssets The quantity of assets that the deposited shares represent
/// @param borrowedAmount The quantity of assets that are currently borrowed
error DepositManager_Insolvent(
address asset,
uint256 requiredAssets,
uint256 depositedSharesInAssets,
uint256 borrowedAmount
);
error DepositManager_ZeroAddress();
error DepositManager_OutOfBounds();
error DepositManager_CannotRescueAsset(address token);
// Asset Configuration Errors
error DepositManager_OperatorNameNotSet(address operator);
error DepositManager_OperatorNameSet(address operator);
error DepositManager_OperatorNameInvalid();
error DepositManager_OperatorNameInUse(string name);
error DepositManager_InvalidAssetPeriod(address asset, uint8 depositPeriod, address operator);
error DepositManager_AssetPeriodExists(address asset, uint8 depositPeriod, address operator);
error DepositManager_AssetPeriodEnabled(address asset, uint8 depositPeriod, address operator);
error DepositManager_AssetPeriodDisabled(address asset, uint8 depositPeriod, address operator);
// Borrowing Errors
error DepositManager_BorrowingLimitExceeded(
address asset,
address operator,
uint256 requested,
uint256 available
);
error DepositManager_BorrowedAmountExceeded(
address asset,
address operator,
uint256 amount,
uint256 borrowed
);
// ========== STRUCTS ========== //
/// @notice Parameters for the {deposit} function
///
/// @param asset The underlying ERC20 asset
/// @param depositPeriod The deposit period, in months
/// @param depositor The depositor
/// @param amount The amount to deposit
/// @param shouldWrap Whether the receipt token should be wrapped
struct DepositParams {
IERC20 asset;
uint8 depositPeriod;
address depositor;
uint256 amount;
bool shouldWrap;
}
/// @notice Parameters for the {withdraw} function
///
/// @param asset The underlying ERC20 asset
/// @param depositPeriod The deposit period, in months
/// @param depositor The depositor that is holding the receipt tokens
/// @param recipient The recipient of the withdrawn asset
/// @param amount The amount to withdraw
/// @param isWrapped Whether the receipt token is wrapped
struct WithdrawParams {
IERC20 asset;
uint8 depositPeriod;
address depositor;
address recipient;
uint256 amount;
bool isWrapped;
}
/// @notice An asset period configuration, representing an asset and period combination
///
/// @param isEnabled Whether the asset period is enabled for new deposits
/// @param depositPeriod The deposit period, in months
/// @param asset The underlying ERC20 asset
/// @param operator The operator that can issue this receipt token
struct AssetPeriod {
bool isEnabled;
uint8 depositPeriod;
address asset;
address operator;
}
/// @notice Status of an asset period
///
/// @param isConfigured Whether the asset period is configured
/// @param isEnabled Whether the asset period is enabled for new deposits
struct AssetPeriodStatus {
bool isConfigured;
bool isEnabled;
}
/// @notice Parameters for borrowing withdrawal operations
///
/// @param asset The underlying ERC20 asset
/// @param recipient The recipient of the borrowed funds
/// @param amount The amount to borrow
struct BorrowingWithdrawParams {
IERC20 asset;
address recipient;
uint256 amount;
}
/// @notice Parameters for borrowing repayment operations
///
/// @param asset The underlying ERC20 asset
/// @param payer The address making the repayment
/// @param amount The amount of principal to repay
/// @param maxAmount The maximum amount that can be repaid
struct BorrowingRepayParams {
IERC20 asset;
address payer;
uint256 amount;
uint256 maxAmount;
}
/// @notice Parameters for borrowing default operations
///
/// @param asset The underlying ERC20 asset
/// @param depositPeriod The deposit period, in months
/// @param payer The address making the default
/// @param amount The amount to default
struct BorrowingDefaultParams {
IERC20 asset;
uint8 depositPeriod;
address payer;
uint256 amount;
}
// ========== BORROWING FUNCTIONS ========== //
/// @notice Borrows funds from deposits
/// @dev The implementing contract is expected to handle the following:
/// - Validating that the caller has the correct role
/// - Validating borrowing limits and capacity
/// - Transferring the underlying asset from the contract to the recipient
/// - Updating borrowing state
/// - Checking solvency
///
/// @param params_ The parameters for the borrowing withdrawal
/// @return actualAmount The quantity of underlying assets transferred to the recipient
function borrowingWithdraw(
BorrowingWithdrawParams calldata params_
) external returns (uint256 actualAmount);
/// @notice Repays borrowed funds
/// @dev The implementing contract is expected to handle the following:
/// - Validating that the caller has the correct role
/// - Transferring the underlying asset from the payer to the contract
/// - Updating borrowing state
/// - Checking solvency
///
/// @param params_ The parameters for the borrowing repayment
/// @return actualAmount The quantity of underlying assets received from the payer
function borrowingRepay(
BorrowingRepayParams calldata params_
) external returns (uint256 actualAmount);
/// @notice Defaults on a borrowed amount
/// @dev The implementing contract is expected to handle the following:
/// - Validating that the caller has the correct role
/// - Burning the receipt tokens from the payer for the default amount
/// - Updating borrowing state
/// - Updating liabilities
function borrowingDefault(BorrowingDefaultParams calldata params_) external;
/// @notice Gets the current borrowed amount for an operator
///
/// @param asset_ The address of the underlying asset
/// @param operator_ The address of the operator
/// @return borrowed The current borrowed amount for the operator
function getBorrowedAmount(
IERC20 asset_,
address operator_
) external view returns (uint256 borrowed);
/// @notice Gets the available borrowing capacity for an operator
///
/// @param asset_ The address of the underlying asset
/// @param operator_ The address of the operator
/// @return capacity The available borrowing capacity for the operator
function getBorrowingCapacity(
IERC20 asset_,
address operator_
) external view returns (uint256 capacity);
// ========== DEPOSIT/WITHDRAW FUNCTIONS ========== //
/// @notice Deposits the given amount of the underlying asset in exchange for a receipt token
/// @dev The implementing contract is expected to handle the following:
/// - Validating that the caller has the correct role
/// - Transferring the underlying asset from the depositor to the contract
/// - Minting the receipt token to the depositor
/// - Updating the amount of deposited funds
///
/// @param params_ The parameters for the deposit
/// @return receiptTokenId The ID of the receipt token
/// @return actualAmount The quantity of receipt tokens minted to the depositor
function deposit(
DepositParams calldata params_
) external returns (uint256 receiptTokenId, uint256 actualAmount);
/// @notice Returns the maximum yield that can be claimed for an asset and operator pair
///
/// @param asset_ The address of the underlying asset
/// @param operator_ The address of the operator
/// @return yieldAssets The amount of yield that can be claimed
function maxClaimYield(
IERC20 asset_,
address operator_
) external view returns (uint256 yieldAssets);
/// @notice Claims the yield from the underlying asset
/// This does not burn receipt tokens, but should reduce the amount of shares the caller has in the vault.
/// @dev The implementing contract is expected to handle the following:
/// - Validating that the caller has the correct role
/// - Transferring the underlying asset from the contract to the recipient
/// - Updating the amount of deposited funds
/// - Checking solvency
///
/// @param asset_ The address of the underlying asset
/// @param recipient_ The recipient of the claimed yield
/// @param amount_ The amount to claim yield for
/// @return actualAmount The quantity of underlying assets transferred to the recipient
function claimYield(
IERC20 asset_,
address recipient_,
uint256 amount_
) external returns (uint256 actualAmount);
/// @notice Withdraws the given amount of the underlying asset
/// @dev The implementing contract is expected to handle the following:
/// - Validating that the caller has the correct role
/// - Burning the receipt token
/// - Transferring the underlying asset from the contract to the recipient
/// - Updating the amount of deposited funds
///
/// @param params_ The parameters for the withdrawal
/// @return actualAmount The quantity of underlying assets transferred to the recipient
function withdraw(WithdrawParams calldata params_) external returns (uint256 actualAmount);
/// @notice Returns the liabilities for an asset and operator pair
///
/// @param asset_ The address of the underlying asset
/// @param operator_ The address of the operator
/// @return liabilities The quantity of assets that the contract is custodying for the operator's depositors
function getOperatorLiabilities(
IERC20 asset_,
address operator_
) external view returns (uint256 liabilities);
// ========== OPERATOR NAMES ========== //
/// @notice Sets the name of an operator. This is included in the name and symbol of receipt tokens.
/// @dev The implementing contract is expected to handle the following:
/// - Validating that the caller has the correct role
/// - Setting the operator name
/// - Emitting an event
function setOperatorName(address operator_, string calldata name_) external;
/// @notice Returns the name of an operator
///
/// @param operator_ The address of the operator
/// @return name The name of the operator or an empty string
function getOperatorName(address operator_) external view returns (string memory name);
// ========== DEPOSIT CONFIGURATIONS ========== //
/// @notice Adds a new asset
/// @dev The implementing contract is expected to handle the following:
/// - Validating that the caller has the correct role
/// - Configuring the asset
/// - Emitting an event
///
/// @param asset_ The address of the underlying asset
/// @param vault_ The address of the ERC4626 vault to deposit the asset into (or the zero address)
/// @param depositCap_ The deposit cap of the asset
/// @param minimumDeposit_ The minimum deposit amount for the asset
function addAsset(
IERC20 asset_,
IERC4626 vault_,
uint256 depositCap_,
uint256 minimumDeposit_
) external;
/// @notice Sets the deposit cap for an asset
/// @dev The implementing contract is expected to handle the following:
/// - Validating that the caller has the correct role
/// - Setting the deposit cap for the asset
/// - Emitting an event
///
/// @param asset_ The address of the underlying asset
/// @param depositCap_ The deposit cap to set for the asset
function setAssetDepositCap(IERC20 asset_, uint256 depositCap_) external;
/// @notice Sets the minimum deposit for an asset
/// @dev The implementing contract is expected to handle the following:
/// - Validating that the caller has the correct role
/// - Setting the minimum deposit for the asset
/// - Emitting an event
///
/// @param asset_ The address of the underlying asset
/// @param minimumDeposit_ The minimum deposit to set for the asset
function setAssetMinimumDeposit(IERC20 asset_, uint256 minimumDeposit_) external;
/// @notice Adds a new asset period
/// @dev The implementing contract is expected to handle the following:
/// - Validating that the caller has the correct role
/// - Creating a new receipt token
/// - Emitting an event
///
/// @param asset_ The address of the underlying asset
/// @param depositPeriod_ The deposit period, in months
/// @param operator_ The address of the operator
/// @return receiptTokenId The ID of the new receipt token
function addAssetPeriod(
IERC20 asset_,
uint8 depositPeriod_,
address operator_
) external returns (uint256 receiptTokenId);
/// @notice Disables an asset period, which prevents new deposits
/// @dev The implementing contract is expected to handle the following:
/// - Validating that the caller has the correct role
/// - Disabling the asset period
/// - Emitting an event
///
/// @param asset_ The address of the underlying asset
/// @param depositPeriod_ The deposit period, in months
/// @param operator_ The address of the operator
function disableAssetPeriod(IERC20 asset_, uint8 depositPeriod_, address operator_) external;
/// @notice Enables an asset period, which allows new deposits
/// @dev The implementing contract is expected to handle the following:
/// - Validating that the caller has the correct role
/// - Enabling the asset period
/// - Emitting an event
///
/// @param asset_ The address of the underlying asset
/// @param depositPeriod_ The deposit period, in months
/// @param operator_ The address of the operator
function enableAssetPeriod(IERC20 asset_, uint8 depositPeriod_, address operator_) external;
/// @notice Returns the asset period for an asset, period and operator
///
/// @param asset_ The address of the underlying asset
/// @param depositPeriod_ The deposit period, in months
/// @param operator_ The address of the operator
/// @return configuration The asset period
function getAssetPeriod(
IERC20 asset_,
uint8 depositPeriod_,
address operator_
) external view returns (AssetPeriod memory configuration);
/// @notice Returns the asset period from a receipt token ID
///
/// @param tokenId_ The ID of the receipt token
/// @return configuration The asset period
function getAssetPeriod(
uint256 tokenId_
) external view returns (AssetPeriod memory configuration);
/// @notice Returns whether a deposit asset, period and operator combination are configured
/// @dev A asset period that is disabled will not accept further deposits
///
/// @param asset_ The address of the underlying asset
/// @param depositPeriod_ The deposit period, in months
/// @param operator_ The address of the operator
/// @return status The status of the asset period
function isAssetPeriod(
IERC20 asset_,
uint8 depositPeriod_,
address operator_
) external view returns (AssetPeriodStatus memory status);
/// @notice Gets all configured asset periods
///
/// @return assetPeriods Array of configured asset periods
function getAssetPeriods() external view returns (AssetPeriod[] memory assetPeriods);
// ========== RECEIPT TOKEN FUNCTIONS ========== //
/// @notice Returns the ID of the receipt token for an asset period and operator
/// @dev The ID returned is not a guarantee that the asset period is configured or enabled. {isAssetPeriod} should be used for that purpose.
///
/// @param asset_ The address of the underlying asset
/// @param depositPeriod_ The deposit period, in months
/// @param operator_ The address of the operator
/// @return receiptTokenId The ID of the receipt token
function getReceiptTokenId(
IERC20 asset_,
uint8 depositPeriod_,
address operator_
) external view returns (uint256 receiptTokenId);
/// @notice Convenience function that returns both receipt token ID and wrapped token address
///
/// @param asset_ The asset contract
/// @param depositPeriod_ The deposit period in months
/// @param operator_ The operator address
/// @return tokenId The receipt token ID
/// @return wrappedToken The address of the wrapped ERC20 token (0x0 if not created yet)
function getReceiptToken(
IERC20 asset_,
uint8 depositPeriod_,
address operator_
) external view returns (uint256 tokenId, address wrappedToken);
/// @notice Gets the receipt token manager
///
/// @return manager The receipt token manager contract
function getReceiptTokenManager() external view returns (IReceiptTokenManager manager);
/// @notice Gets all receipt token IDs owned by this contract
///
/// @return tokenIds Array of receipt token IDs
function getReceiptTokenIds() external view returns (uint256[] memory tokenIds);
}
"
},
"src/policies/interfaces/deposits/IDepositRedemptionVault.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
// Interfaces
import {IERC20} from "src/interfaces/IERC20.sol";
/// @title IDepositRedemptionVault
/// @notice Interface for a contract that can manage the redemption of receipt tokens for their deposit
interface IDepositRedemptionVault {
// ========== EVENTS ========== //
event RedemptionStarted(
address indexed user,
uint16 indexed redemptionId,
address indexed depositToken,
uint8 depositPeriod,
uint256 amount,
address facility
);
event RedemptionFinished(
address indexed user,
uint16 indexed redemptionId,
address indexed depositToken,
uint8 depositPeriod,
uint256 amount
);
event RedemptionCancelled(
address indexed user,
uint16 indexed redemptionId,
address indexed depositToken,
uint8 depositPeriod,
uint256 amount,
uint256 remainingAmount
);
// Borrowing Events
event LoanCreated(
address indexed user,
uint16 indexed redemptionId,
uint256 amount,
address facility
);
event LoanRepaid(
address indexed user,
uint16 indexed redemptionId,
uint256 principal,
uint256 interest
);
event LoanExtended(address indexed user, uint16 indexed redemptionId, uint256 newDueDate);
event LoanDefaulted(
address indexed user,
uint16 indexed redemptionId,
uint256 principal,
uint256 interest,
uint256 remainingCollateral
);
event FacilityAuthorized(address indexed facility);
event FacilityDeauthorized(address indexed facility);
event AnnualInterestRateSet(address indexed asset, address indexed facility, uint16 rate);
event MaxBorrowPercentageSet(address indexed asset, address indexed facility, uint16 percent);
event ClaimDefaultRewardPercentageSet(uint16 percent);
// ========== ERRORS ========== //
error RedemptionVault_InvalidDepositManager(address depositManager);
error RedemptionVault_ZeroAmount();
error RedemptionVault_InvalidRedemptionId(address user, uint16 redemptionId);
error RedemptionVault_InvalidAmount(address user, uint16 redemptionId, uint256 amount);
error RedemptionVault_TooEarly(address user, uint16 redemptionId, uint48 redeemableAt);
error RedemptionVault_AlreadyRedeemed(address user, uint16 redemptionId);
error RedemptionVault_ZeroAddress();
error RedemptionVault_OutOfBounds(uint16 rate);
error RedemptionVault_UnpaidLoan(address user, uint16 redemptionId);
// Facility Authorization
error RedemptionVault_InvalidFacility(address facility);
error RedemptionVault_FacilityExists(address facility);
error RedemptionVault_FacilityNotRegistered(address facility);
// Borrowing Errors
error RedemptionVault_InterestRateNotSet(address asset, address facility);
error RedemptionVault_LoanAmountExceeded(address user, uint16 redemptionId, uint256 amount);
error RedemptionVault_LoanIncorrectState(address user, uint16 redemptionId);
error RedemptionVault_InvalidLoan(address user, uint16 redemptionId);
error RedemptionVault_MaxSlippageExceeded(
address user,
uint16 redemptionId,
uint256 actualAmount,
uint256 maxAmount
);
// ========== DATA STRUCTURES ========== //
/// @notice Data structure for a redemption of a receipt token
///
/// @param depositToken The address of the deposit token
/// @param depositPeriod The period of the deposit in months
/// @param redeemableAt The timestamp at which the redemption can be finished
/// @param amount The amount of deposit tokens to redeem
/// @param facility The facility that handles this redemption
/// @param positionId The position ID for position-based redemptions (type(uint256).max without a position)
struct UserRedemption {
address depositToken;
uint8 depositPeriod;
uint48 redeemableAt;
uint256 amount;
address facility;
uint256 positionId;
}
/// @notice Data structure for a loan against a redemption
///
/// @param initialPrincipal The initial principal amount borrowed
/// @param principal The principal owed
/// @param interest The interest owed
/// @param dueDate The timestamp when the loan is due
/// @param isDefaulted Whether the loan has defaulted
struct Loan {
uint256 initialPrincipal;
uint256 principal;
uint256 interest;
uint48 dueDate;
bool isDefaulted;
}
// ========== FACILITY MANAGEMENT ========== //
/// @notice Authorize a facility
///
/// @param facility_ The address of the facility to authorize
function authorizeFacility(address facility_) external;
/// @notice Deauthorize a facility
///
/// @param facility_ The address of the facility to deauthorize
function deauthorizeFacility(address facility_) external;
/// @notice Check if a facility is authorized
///
/// @param facility_ The address of the facility to check
/// @return isAuthorized True if the facility is authorized
function isAuthorizedFacility(address facility_) external view returns (bool isAuthorized);
/// @notice Get all authorized facilities
///
/// @return facilities Array of authorized facility addresses
function getAuthorizedFacilities() external view returns (address[] memory facilities);
// ========== REDEMPTION FLOW ========== //
/// @notice Gets the details of a user's redemption
///
/// @param user_ The address of the user
/// @param redemptionId_ The ID of the redemption
/// @return redemption The details of the redemption
function getUserRedemption(
address user_,
uint16 redemptionId_
) external view returns (UserRedemption memory redemption);
/// @notice Gets the number of redemptions a user has started
///
/// @param user_ The address of the user
/// @return count The number of redemptions
function getUserRedemptionCount(address user_) external view returns (uint16 count);
/// @notice Gets all redemptions for a user
///
/// @param user_ The address of the user
/// @return redemptions The array of redemptions
function getUserRedemptions(address user_) external view returns (UserRedemption[] memory);
/// @notice Starts a redemption of a quantity of deposit tokens
///
/// @param depositToken_ The address of the deposit token
/// @param depositPeriod_ The period of the deposit in months
/// @param amount_ The amount of deposit tokens to redeem
/// @param facility_ The facility to handle this redemption
/// @return redemptionId The ID of the user redemption
function startRedemption(
IERC20 depositToken_,
uint8 depositPeriod_,
uint256 amount_,
address facility_
) external returns (uint16 redemptionId);
/// @notice Starts a redemption based on a position ID, using the position's conversion expiry
///
/// @param positionId_ The ID of the position to redeem from
/// @param amount_ The amount of deposit tokens to redeem
/// @return redemptionId The ID of the user redemption
function startRedemption(
uint256 positionId_,
uint256 amount_
) external returns (uint16 redemptionId);
/// @notice Cancels a redemption of a quantity of deposit tokens
///
/// @param redemptionId_ The ID of the user redemption
/// @param amount_ The amount of deposit tokens to cancel
function cancelRedemption(uint16 redemptionId_, uint256 amount_) external;
/// @notice Finishes a redemption of a quantity of deposit tokens
/// @dev This function does not take an amount as an argument, because the amount is determined by the redemption
///
/// @param redemptionId_ The ID of the user redemption
/// @return actualAmount The quantity of deposit tokens transferred to the caller
function finishRedemption(uint16 redemptionId_) external returns (uint256 actualAmount);
// ========== BORROWING FUNCTIONS ========== //
/// @notice Borrow the maximum amount against an active redemption
///
/// @param redemptionId_ The ID of the redemption to borrow against
/// @return actualAmount The quantity of underlying assets transferred to the recipient
function borrowAgainstRedemption(uint16 redemptionId_) external returns (uint256 actualAmount);
/// @notice Preview the maximum amount that can be borrowed against an active redemption
///
/// @param user_ The address of the user
/// @param redemptionId_ The ID of the redemption to borrow against
/// @return principal The principal amount that can be borrowed
/// @return interest The interest amount that will be charged
/// @return dueDate The due date of the loan
function previewBorrowAgainstRedemption(
address user_,
uint16 redemptionId_
) external view returns (uint256 principal, uint256 interest, uint48 dueDate);
/// @notice Repay a loan
///
/// @param redemptionId_ The ID of the redemption
/// @param amount_ The amount to repay
/// @param maxSlippage_ The maximum slippage allowed for the repayment
function repayLoan(uint16 redemptionId_, uint256 amount_, uint256 maxSlippage_) external;
/// @notice Preview the interest payable for extending a loan
///
/// @param user_ The address of the user
/// @param redemptionId_ The ID of the redemption
/// @param months_ The number of months to extend the loan
/// @return newDueDate The new due date
/// @return interestPayable The interest payable upon extension
function previewExtendLoan(
address user_,
uint16 redemptionId_,
uint8 months_
) external view returns (uint48 newDueDate, uint256 interestPayable);
/// @notice Extend a loan's due date
///
/// @param redemptionId_ The ID of the redemption
/// @param months_ The number of months to extend the loan
function extendLoan(uint16 redemptionId_, uint8 months_) external;
/// @notice Claim a defaulted loan and collect the reward
///
/// @param user_ The address of the user
/// @param redemptionId_ The ID of the redemption
function claimDefaultedLoan(address user_, uint16 redemptionId_) external;
// ========== BORROWING VIEW FUNCTIONS ========== //
/// @notice Get all loans for a redemption
///
/// @param user_ The address of the user
/// @param redemptionId_ The ID of the redemption
/// @return loan The loan
function getRedemptionLoan(
address user_,
uint16 redemptionId_
) external view returns (Loan memory loan);
// ========== ADMIN FUNCTIONS ========== //
/// @notice Set the maximum borrow percentage for an asset-facility combination
///
/// @param asset_ The address of the asset
/// @param facility_ The address of the facility
/// @param percent_ The maximum borrow percentage
function setMaxBorrowPercentage(IERC20 asset_, address facility_, uint16 percent_) external;
/// @notice Get the maximum borrow percentage for an asset-facility combination
///
/// @param asset_ The address of the asset
/// @param facility_ The address of the facility
/// @return percent The maximum borrow percentage (100e2 == 100%)
function getMaxBorrowPercentage(
IERC20 asset_,
address facility_
) external view returns (uint16 percent);
/// @notice Set the annual interest rate for an asset-facility combination
///
/// @param asset_ The address of the asset
/// @param facility_ The address of the facility
/// @param rate_ The annual interest rate (100e2 == 100%)
function setAnnualInterestRate(IERC20 asset_, address facility_, uint16 rate_) external;
/// @notice Get the annual interest rate for an asset-facility combination
///
/// @param asset_ The address of the asset
/// @param facility_ The address of the facility
/// @return rate The annual interest rate, in terms of 100e2
function getAnnualInterestRate(
IERC20 asset_,
address facility_
) external view returns (uint16 rate);
/// @notice Set the reward percentage when a claiming a defaulted loan
///
/// @param percent_ The claim default reward percentage
function setClaimDefaultRewardPercentage(uint16 percent_) external;
/// @notice Get the claim default reward percentage
///
/// @return percent The claim default reward percentage, in terms of 100e2
function getClaimDefaultRewardPercentage() external view returns (uint16 percent);
}
"
},
"src/policies/interfaces/deposits/IDepositFacility.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
// Interfaces
import {IERC20} from "src/interfaces/IERC20.sol";
/// @title IDepositFacility
/// @notice Interface for deposit facilities to coordinate with generic operators (e.g., redemption vaults)
interface IDepositFacility {
// ========== EVENTS ========== //
event OperatorAuthorized(address indexed operator);
event OperatorDeauthorized(address indexed operator);
event AssetCommitted(address indexed asset, address indexed operator, uint256 amount);
event AssetCommitCancelled(address indexed asset, address indexed operator, uint256 amount);
event AssetCommitWithdrawn(address indexed asset, address indexed operator, uint256 amount);
event Reclaimed(
address indexed user,
address indexed depositToken,
uint8 depositPeriod,
uint256 reclaimedAmount,
uint256 forfeitedAmount
);
event AssetPeriodReclaimRateSet(address indexed asset, uint8 depositPeriod, uint16 reclaimRate);
// ========== ERRORS ========== //
error DepositFacility_ZeroAmount();
error DepositFacility_InvalidAddress(address operator);
error DepositFacility_UnauthorizedOperator(address operator);
error DepositFacility_InsufficientDeposits(uint256 requested, uint256 available);
error DepositFacility_InsufficientCommitment(
address operator,
uint256 requested,
uint256 available
);
error DepositFacility_InvalidReclaimRate(uint16 reclaimRate, uint16 maxReclaimRate);
// ========== OPERATOR AUTHORIZATION ========== //
/// @notice Authorize an operator (e.g., a redemption vault) to handle actions through this facility
///
/// @param operator_ The address of the operator to authorize
function authorizeOperator(address operator_) external;
/// @notice Deauthorize an operator
///
/// @param operator_ The address of the operator to deauthorize
function deauthorizeOperator(address operator_) external;
/// @notice Check if an operator is authorized
///
/// @param operator_ The address of the operator to check
/// @return isAuthorized True if the operator is authorized
function isAuthorizedOperator(address operator_) external view returns (bool isAuthorized);
/// @notice Get the list of operators authorized to handle actions through this facility
///
/// @return operators The list of operators
function getOperators() external view returns (address[] memory operators);
// ========== REDEMPTION HANDLING ========== //
/// @notice Allows an operator to commit funds. This will ensure that enough funds are available to honour the commitments.
///
/// @param depositToken_ The deposit token committed
/// @param depositPeriod_ The deposit period in months
///
Submitted on: 2025-11-07 16:50:32
Comments
Log in to comment.
No comments yet.