ConvertibleDepositActivator

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
    /// 

Tags:
ERC20, ERC165, Multisig, Mintable, Burnable, Swap, Yield, Voting, Timelock, Multi-Signature, Factory, Oracle|addr:0x5261fba7b50aa22b19b9edf939b771d109de991f|verified:true|block:23748095|tx:0x3344fa4f1f8348444ac805a17ed80fd6ad0735c567411ddc44372ef0699f57fa|first_check:1762530631

Submitted on: 2025-11-07 16:50:32

Comments

Log in to comment.

No comments yet.