Skip to main content

DepositManager

Git Source

Inherits: Policy, PolicyEnabler, IDepositManager, BaseAssetManager

Title: Deposit Manager

forge-lint: disable-start(asm-keccak256, mixed-case-function)

This policy manages deposits and withdrawals for Olympus protocol contracts

Key Features:

  • ERC6909 receipt tokens with optional ERC20 wrapping, using ReceiptTokenManager
  • Operator isolation preventing cross-operator fund access
  • Borrowing functionality
  • Configurable reclaim rates for risk management

State Variables

ROLE_DEPOSIT_OPERATOR

The role that is allowed to deposit and withdraw funds

bytes32 public constant ROLE_DEPOSIT_OPERATOR = "deposit_operator"

_RECEIPT_TOKEN_MANAGER

The receipt token manager for creating receipt tokens

ReceiptTokenManager internal immutable _RECEIPT_TOKEN_MANAGER

_assetLiabilities

Maps asset liabilities key to the number of receipt tokens that have been minted

This is used to ensure that the receipt tokens are solvent As with the BaseAssetManager, deposited asset tokens with different deposit periods are co-mingled.

mapping(bytes32 key => uint256 receiptTokenSupply) internal _assetLiabilities

_assetPeriods

Maps token ID to the asset period

mapping(uint256 tokenId => AssetPeriod) internal _assetPeriods

_ownedTokenIds

Set of token IDs that this DepositManager owns

EnumerableSet.UintSet internal _ownedTokenIds

ONE_HUNDRED_PERCENT

Constant equivalent to 100%

uint16 public constant ONE_HUNDRED_PERCENT = 100e2

_operatorToName

Maps operator address to its name

mapping(address operator => bytes3 name) internal _operatorToName

_operatorNames

A set of operator names

This contains unique values

mapping(bytes3 name => bool isRegistered) internal _operatorNames

_borrowedAmounts

Maps asset-operator key to current borrowed amounts

The key is the keccak256 of the asset address and the operator address

mapping(bytes32 key => uint256 borrowedAmount) internal _borrowedAmounts

Functions

_onlyAssetPeriodExists

function _onlyAssetPeriodExists(IERC20 asset_, uint8 depositPeriod_, address operator_) internal view;

onlyAssetPeriodExists

Reverts if the asset period is not configured

modifier onlyAssetPeriodExists(IERC20 asset_, uint8 depositPeriod_, address operator_) ;

_onlyAssetPeriodEnabled

function _onlyAssetPeriodEnabled(IERC20 asset_, uint8 depositPeriod_, address operator_) internal view;

onlyAssetPeriodEnabled

Reverts if the asset period is not enabled

modifier onlyAssetPeriodEnabled(IERC20 asset_, uint8 depositPeriod_, address operator_) ;

constructor

constructor(address kernel_, address tokenManager_) Policy(Kernel(kernel_));

configureDependencies

Define module dependencies for this policy.

function configureDependencies() external override returns (Keycode[] memory dependencies);

Returns

NameTypeDescription
dependenciesKeycode[]- Keycode array of module dependencies.

requestPermissions

Function called by kernel to set module function permissions.

function requestPermissions() external view override returns (Permissions[] memory permissions);

Returns

NameTypeDescription
permissionsPermissions[]requests - Array of keycodes and function selectors for requested permissions.

VERSION

function VERSION() external pure returns (uint8 major, uint8 minor);

deposit

Deposits the given amount of the underlying asset in exchange for a receipt token

This function is only callable by addresses with the deposit operator role The actions of the calling deposit operator are restricted to its own namespace, preventing the operator from accessing funds of other operators. This function reverts if:

  • The contract is not enabled
  • The caller does not have the deposit operator role
  • The asset/deposit period/operator combination is not enabled
  • The deposit amount is below the minimum deposit requirement
  • The deposit would exceed the asset's deposit cap for the operator
  • The depositor has not approved the DepositManager to spend the asset tokens
  • The depositor has insufficient asset token balance
  • The asset is a fee-on-transfer token
  • Zero shares would be received from the vault
function deposit(DepositParams calldata params_)
external
onlyEnabled
onlyRole(ROLE_DEPOSIT_OPERATOR)
onlyAssetPeriodEnabled(params_.asset, params_.depositPeriod, msg.sender)
returns (uint256 receiptTokenId, uint256 actualAmount);

Parameters

NameTypeDescription
params_DepositParamsThe parameters for the deposit

Returns

NameTypeDescription
receiptTokenIduint256The ID of the receipt token
actualAmountuint256The quantity of receipt tokens minted to the depositor

maxClaimYield

Returns the maximum yield that can be claimed for an asset and operator pair

The actions of the calling deposit operator are restricted to its own namespace, preventing the operator from accessing funds of other operators. Note that the returned value is a theoretical maximum. The theoretical value may not be accurate or possible due to rounding and other behaviours in an ERC4626 vault.

function maxClaimYield(IERC20 asset_, address operator_) external view returns (uint256);

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
operator_addressThe address of the operator

Returns

NameTypeDescription
<none>uint256yieldAssets The amount of yield that can be claimed

claimYield

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.

Notes:

  • This function is only callable by addresses with the deposit operator role
  • The actions of the calling deposit operator are restricted to its own namespace, preventing the operator from accessing funds of other operators.
  • Given a low enough amount, the actual amount withdrawn may be 0. This function will not revert in such a case. This function reverts if:
  • The contract is not enabled
  • The caller does not have the deposit operator role
  • The asset is not configured in BaseAssetManager
  • The operator becomes insolvent after the withdrawal (assets + borrowed < liabilities)
function claimYield(IERC20 asset_, address recipient_, uint256 amount_)
external
onlyEnabled
onlyRole(ROLE_DEPOSIT_OPERATOR)
onlyConfiguredAsset(asset_)
returns (uint256 actualAmount);

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
recipient_addressThe recipient of the claimed yield
amount_uint256The amount to claim yield for

Returns

NameTypeDescription
actualAmountuint256The quantity of underlying assets transferred to the recipient

withdraw

Withdraws the given amount of the underlying asset

Notes:

  • This function is only callable by addresses with the deposit operator role
  • The actions of the calling deposit operator are restricted to its own namespace, preventing the operator from accessing funds of other operators.
  • Given a low enough amount, the actual amount withdrawn may be 0. This function will not revert in such a case. This function will revert if:
  • The contract is not enabled
  • The caller does not have the deposit operator role
  • The recipient is the zero address
  • The asset/deposit period/operator combination is not configured
  • The depositor has insufficient receipt token balance
  • For wrapped tokens: depositor has not approved ReceiptTokenManager to spend the wrapped ERC20 token
  • For unwrapped tokens: depositor has not approved the caller to spend ERC6909 tokens
  • The operator becomes insolvent after the withdrawal (assets + borrowed < liabilities)
function withdraw(WithdrawParams calldata params_)
external
onlyEnabled
onlyRole(ROLE_DEPOSIT_OPERATOR)
returns (uint256 actualAmount);

Parameters

NameTypeDescription
params_WithdrawParamsThe parameters for the withdrawal

Returns

NameTypeDescription
actualAmountuint256The quantity of underlying assets transferred to the recipient

getOperatorLiabilities

Returns the liabilities for an asset and operator pair

function getOperatorLiabilities(IERC20 asset_, address operator_) external view returns (uint256);

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
operator_addressThe address of the operator

Returns

NameTypeDescription
<none>uint256liabilities The quantity of assets that the contract is custodying for the operator's depositors

_getAssetLiabilitiesKey

Get the key for the asset liabilities mapping

The key is the keccak256 of the asset address and the operator address

function _getAssetLiabilitiesKey(IERC20 asset_, address operator_) internal pure returns (bytes32);

_validateOperatorSolvency

Validates that an operator remains solvent after a withdrawal

This function ensures that operator assets + borrowed amount >= operator liabilities This is the core solvency constraint for the DepositManager Notes:

  • The solvency checks assume that the value of each vault share is increasing, and will not reduce.
  • In a situation where the assets per share reduces below 1 (at the appropriate decimal scale), the solvency check will fail.
function _validateOperatorSolvency(IERC20 asset_, address operator_) internal view;

Parameters

NameTypeDescription
asset_IERC20The asset to validate solvency for
operator_addressThe operator to validate solvency for

setOperatorName

Sets the name of an operator. This is included in the name and symbol of receipt tokens.

Note that once set, an operator name cannot be changed. This function reverts if:

  • The contract is not enabled
  • The caller does not have the admin or manager role
  • The operator's name is already set
  • The name is already in use by another operator
  • The operator name is empty
  • The operator name is not exactly 3 characters long
  • The operator name contains characters that are not a-z or 0-9
function setOperatorName(address operator_, string calldata name_) external onlyEnabled onlyManagerOrAdminRole;

getOperatorName

Returns the name of an operator

function getOperatorName(address operator_) public view returns (string memory);

Parameters

NameTypeDescription
operator_addressThe address of the operator

Returns

NameTypeDescription
<none>stringname The name of the operator or an empty string

isAssetPeriod

Returns whether a deposit asset, period and operator combination are configured

A asset period that is disabled will not accept further deposits

function isAssetPeriod(IERC20 asset_, uint8 depositPeriod_, address operator_)
public
view
override
returns (AssetPeriodStatus memory status);

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
depositPeriod_uint8The deposit period, in months
operator_addressThe address of the operator

Returns

NameTypeDescription
statusAssetPeriodStatusThe status of the asset period

addAsset

Adds a new asset

This function reverts if:

  • The contract is not enabled
  • The caller does not have the admin or manager role
  • asset_ is the zero address
  • minimumDeposit> depositCap Notes:
  • A limitation of the current implementation is that the vault is assumed to be monotonically-increasing in value.
  • The pairing of the asset and vault is immutable, to prevent a governance attack on user deposits.
function addAsset(IERC20 asset_, IERC4626 vault_, uint256 depositCap_, uint256 minimumDeposit_)
external
onlyEnabled
onlyManagerOrAdminRole;

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
vault_IERC4626The address of the ERC4626 vault to deposit the asset into (or the zero address)
depositCap_uint256The deposit cap of the asset
minimumDeposit_uint256The minimum deposit amount for the asset

setAssetDepositCap

Sets the deposit cap for an asset

This function reverts if:

  • The contract is not enabled
  • The caller does not have the admin or manager role
  • asset_ is not configured
  • The existing minimum deposit > depositCap_
function setAssetDepositCap(IERC20 asset_, uint256 depositCap_) external onlyEnabled onlyManagerOrAdminRole;

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
depositCap_uint256The deposit cap to set for the asset

setAssetMinimumDeposit

Sets the minimum deposit for an asset

This function reverts if:

  • The contract is not enabled
  • The caller does not have the admin or manager role
  • asset_ is not configured
  • minimumDeposit_ > the existing deposit cap
function setAssetMinimumDeposit(IERC20 asset_, uint256 minimumDeposit_)
external
onlyEnabled
onlyManagerOrAdminRole;

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
minimumDeposit_uint256The minimum deposit to set for the asset

addAssetPeriod

Adds a new asset period

This function is only callable by the manager or admin role This function reverts if:

  • The contract is not enabled
  • The caller does not have the manager or admin role
  • The asset has not been added via addAsset()
  • The operator is the zero address
  • The deposit period is 0
  • The asset/deposit period/operator combination is already configured
  • The operator name has not been set
  • Receipt token creation fails (invalid parameters in ReceiptTokenManager)
function addAssetPeriod(IERC20 asset_, uint8 depositPeriod_, address operator_)
external
onlyEnabled
onlyManagerOrAdminRole
onlyConfiguredAsset(asset_)
returns (uint256 receiptTokenId);

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
depositPeriod_uint8The deposit period, in months
operator_addressThe address of the operator

Returns

NameTypeDescription
receiptTokenIduint256The ID of the new receipt token

enableAssetPeriod

Enables an asset period, which allows new deposits

This function is only callable by the manager or admin role This function reverts if:

  • The contract is not enabled
  • The caller does not have the manager or admin role
  • The asset/deposit period/operator combination does not exist
  • The asset period is already enabled
function enableAssetPeriod(IERC20 asset_, uint8 depositPeriod_, address operator_)
external
onlyEnabled
onlyManagerOrAdminRole
onlyAssetPeriodExists(asset_, depositPeriod_, operator_);

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
depositPeriod_uint8The deposit period, in months
operator_addressThe address of the operator

disableAssetPeriod

Disables an asset period, which prevents new deposits

This function is only callable by the manager or admin role This function reverts if:

  • The contract is not enabled
  • The caller does not have the manager or admin role
  • The asset/deposit period/operator combination does not exist
  • The asset period is already disabled
function disableAssetPeriod(IERC20 asset_, uint8 depositPeriod_, address operator_)
external
onlyEnabled
onlyManagerOrAdminRole
onlyAssetPeriodExists(asset_, depositPeriod_, operator_);

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
depositPeriod_uint8The deposit period, in months
operator_addressThe address of the operator

getAssetPeriods

Gets all configured asset periods

function getAssetPeriods() external view override returns (AssetPeriod[] memory assetPeriods);

Returns

NameTypeDescription
assetPeriodsAssetPeriod[]Array of configured asset periods

getAssetPeriod

Returns the asset period from a receipt token ID

function getAssetPeriod(uint256 tokenId_) public view override returns (AssetPeriod memory);

Parameters

NameTypeDescription
tokenId_uint256The ID of the receipt token

Returns

NameTypeDescription
<none>AssetPeriodconfiguration The asset period

getAssetPeriod

Returns the asset period for an asset, period and operator

function getAssetPeriod(IERC20 asset_, uint8 depositPeriod_, address operator_)
public
view
override
returns (AssetPeriod memory);

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
depositPeriod_uint8The deposit period, in months
operator_addressThe address of the operator

Returns

NameTypeDescription
<none>AssetPeriodconfiguration The asset period

borrowingWithdraw

Borrows funds from deposits

Notes:

  • This function is only callable by addresses with the deposit operator role
  • Given a low enough amount, the actual amount withdrawn may be 0. This function will not revert in such a case. This function reverts if:
  • The contract is not enabled
  • The caller does not have the deposit operator role
  • The recipient is the zero address
  • The asset has not been added via addAsset()
  • The amount exceeds the operator's available borrowing capacity
  • The operator becomes insolvent after the withdrawal (assets + borrowed < liabilities)
function borrowingWithdraw(BorrowingWithdrawParams calldata params_)
external
onlyEnabled
onlyRole(ROLE_DEPOSIT_OPERATOR)
returns (uint256 actualAmount);

Parameters

NameTypeDescription
params_BorrowingWithdrawParamsThe parameters for the borrowing withdrawal

Returns

NameTypeDescription
actualAmountuint256The quantity of underlying assets transferred to the recipient

borrowingRepay

Repays borrowed funds

Notes:

  • This function is only callable by addresses with the deposit operator role
  • This function does not check for over-payment. It is expected to be handled by the calling contract.
  • If the actual amount repaid is greater than the maximum amount provided, updates to the state variables are capped at the maximum amount. This function reverts if:
  • The contract is not enabled
  • The caller does not have the deposit operator role
  • The asset has not been added via addAsset()
  • The payer has not approved DepositManager to spend the asset tokens
  • The payer has insufficient asset token balance
  • The asset is a fee-on-transfer token
  • Zero shares would be deposited into the vault
  • The operator becomes insolvent after the repayment (assets + borrowed < liabilities)
function borrowingRepay(BorrowingRepayParams calldata params_)
external
onlyEnabled
onlyRole(ROLE_DEPOSIT_OPERATOR)
returns (uint256 actualAmount);

Parameters

NameTypeDescription
params_BorrowingRepayParamsThe parameters for the borrowing repayment

Returns

NameTypeDescription
actualAmountuint256The quantity of underlying assets received from the payer

borrowingDefault

Defaults on a borrowed amount

This function is only callable by addresses with the deposit operator role This function reverts if:

  • The contract is not enabled
  • The caller does not have the deposit operator role
  • The asset has not been added via addAsset()
  • The amount exceeds the current borrowed amount for the operator
  • The payer has insufficient receipt token balance
  • The payer has not approved the caller to spend ERC6909 tokens
  • The operator becomes insolvent after the default (assets + borrowed < liabilities)
function borrowingDefault(BorrowingDefaultParams calldata params_)
external
onlyEnabled
onlyRole(ROLE_DEPOSIT_OPERATOR);

getBorrowedAmount

Gets the current borrowed amount for an operator

function getBorrowedAmount(IERC20 asset_, address operator_) public view returns (uint256 borrowed);

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
operator_addressThe address of the operator

Returns

NameTypeDescription
borroweduint256The current borrowed amount for the operator

getBorrowingCapacity

Gets the available borrowing capacity for an operator

function getBorrowingCapacity(IERC20 asset_, address operator_) public view returns (uint256 capacity);

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
operator_addressThe address of the operator

Returns

NameTypeDescription
capacityuint256The available borrowing capacity for the operator

_setReceiptTokenData

function _setReceiptTokenData(IERC20 asset_, uint8 depositPeriod_, address operator_)
internal
returns (uint256 tokenId);

getReceiptTokenId

Returns the ID of the receipt token for an asset period and operator

The ID returned is not a guarantee that the asset period is configured or enabled. {isAssetPeriod} should be used for that purpose.

function getReceiptTokenId(IERC20 asset_, uint8 depositPeriod_, address operator_)
public
view
override
returns (uint256);

Parameters

NameTypeDescription
asset_IERC20The address of the underlying asset
depositPeriod_uint8The deposit period, in months
operator_addressThe address of the operator

Returns

NameTypeDescription
<none>uint256receiptTokenId The ID of the receipt token

getReceiptTokenManager

Gets the receipt token manager

function getReceiptTokenManager() external view override returns (IReceiptTokenManager);

Returns

NameTypeDescription
<none>IReceiptTokenManagermanager The receipt token manager contract

getReceiptTokenIds

Gets all receipt token IDs owned by this contract

function getReceiptTokenIds() external view override returns (uint256[] memory);

Returns

NameTypeDescription
<none>uint256[]tokenIds Array of receipt token IDs

getReceiptToken

Convenience function that returns both receipt token ID and wrapped token address

function getReceiptToken(IERC20 asset_, uint8 depositPeriod_, address operator_)
external
view
override
returns (uint256 tokenId, address wrappedToken);

Parameters

NameTypeDescription
asset_IERC20The asset contract
depositPeriod_uint8The deposit period in months
operator_addressThe operator address

Returns

NameTypeDescription
tokenIduint256The receipt token ID
wrappedTokenaddressThe address of the wrapped ERC20 token (0x0 if not created yet)

supportsInterface

function supportsInterface(bytes4 interfaceId)
public
view
virtual
override(BaseAssetManager, PolicyEnabler)
returns (bool);

rescue

Rescue any ERC20 token sent to this contract and send it to the TRSRY

This function reverts if:

  • The caller does not have the admin role
  • token_ is a managed asset or vault
  • token_ is the zero address
function rescue(address token_) external onlyEnabled onlyAdminRole;

Parameters

NameTypeDescription
token_addressThe address of the ERC20 token to rescue