Skip to main content

MonoCooler

Git Source

Inherits: IMonoCooler, Policy, PolicyAdmin

Title: Mono Cooler

A borrow/lend market where users can deposit their gOHM as collateral and then borrow a stablecoin debt token up to a certain LTV

  • The debt token may change over time - eg DAI to USDS (or USDC), determined by the CoolerTreasuryBorrower
  • The collateral and debt amounts tracked on this contract are always reported in wad, ie 18 decimal places
  • gOHM collateral can be delegated to accounts for voting, via the DLGTE module
  • Positions can be liquidated if the LTV breaches the 'liquidation LTV' as determined by the LTV Oracle
  • Users may set an authorization for one other address to act on its behalf.

Constants​

_COLLATERAL_TOKEN​

The collateral token, eg gOHM

ERC20 private immutable _COLLATERAL_TOKEN;

_OHM​

The OHM token

ERC20 private immutable _OHM;

_STAKING​

The OHM staking contract

IStaking private immutable _STAKING;

_MIN_DEBT_REQUIRED​

The minimum debt a user needs to maintain

uint256 private immutable _MIN_DEBT_REQUIRED;

DOMAIN_SEPARATOR​

Returns the domain separator used in the encoding of the signature for setAuthorizationWithSig(), as defined by EIP712.

bytes32 public immutable override DOMAIN_SEPARATOR;

Returns

NameTypeDescription
<none>bytes32

_RAY​

Extra precision scalar

uint256 private constant _RAY = 1e27;

_DOMAIN_TYPEHASH​

The EIP-712 typeHash for EIP712Domain.

bytes32 private constant _DOMAIN_TYPEHASH =
keccak256("EIP712Domain(uint256 chainId,address verifyingContract)");

_AUTHORIZATION_TYPEHASH​

The EIP-712 typeHash for Authorization.

bytes32 private constant _AUTHORIZATION_TYPEHASH =
keccak256(
"Authorization(address account,address authorized,uint96 authorizationDeadline,uint256 nonce,uint256 signatureDeadline)"
);

_EXPECTED_DECIMALS​

expected decimals for the _COLLATERAL_TOKEN and treasuryBorrower

uint8 private constant _EXPECTED_DECIMALS = 18;

MAX_INTEREST_RATE​

Cannot set an interest rate higher than 10%

uint96 private constant MAX_INTEREST_RATE = 0.1e18;

State Variables​

MINTR​

MINTRv1 public MINTR;

DLGTE​

DLGTEv1 public DLGTE;

totalCollateral​

The total amount of collateral posted across all accounts.

To 18 decimal places

uint128 public override totalCollateral;

Returns

NameTypeDescription
<none>uint128

totalDebt​

The total amount of debt which has been borrowed across all users as of the latest checkpoint

To 18 decimal places

uint128 public override totalDebt;

Returns

NameTypeDescription
<none>uint128

interestAccumulatorRay​

The accumulator index used to track the compounding of debt, starting at 1e27 at genesis

To RAY (1e27) precision

uint256 public override interestAccumulatorRay;

Returns

NameTypeDescription
<none>uint256

interestRateWad​

The flat interest rate (APR).

Interest (approximately) continuously compounds at this rate.

To 18 decimal places

uint96 public override interestRateWad;

Returns

NameTypeDescription
<none>uint96

ltvOracle​

The oracle serving both the Max Origination LTV and the Liquidation LTV

ICoolerLtvOracle public override ltvOracle;

Returns

NameTypeDescription
<none>address

liquidationsPaused​

Liquidations may be paused in order for users to recover/repay debt after emergency actions or interest rate changes

bool public override liquidationsPaused;

Returns

NameTypeDescription
<none>bool

borrowsPaused​

Borrows may be paused for emergency actions or deprecating the facility

bool public override borrowsPaused;

Returns

NameTypeDescription
<none>bool

interestAccumulatorUpdatedAt​

The last time the global debt accumulator was updated

uint40 public override interestAccumulatorUpdatedAt;

Returns

NameTypeDescription
<none>uint40

treasuryBorrower​

The policy which borrows/repays from Treasury on behalf of Cooler

ICoolerTreasuryBorrower public override treasuryBorrower;

Returns

NameTypeDescription
<none>address

allAccountState​

A per account store, tracking collateral/debt as of their latest checkpoint.

mapping(address /* account */ => AccountState) private allAccountState;

authorizations​

Whether authorized is authorized to act on authorizer's behalf for all user actions up until the authorizationDeadline unix timestamp.

Anyone is authorized to modify their own positions, regardless of this variable.

mapping(address /* account */ => mapping(address /* authorized */ => uint96 /* authorizationDeadline */))
public
override authorizations;

Parameters

NameTypeDescription
<none>address
<none>address

Returns

NameTypeDescription
<none>uint96

authorizationNonces​

The authorizer's current nonce. Used to prevent replay attacks with EIP-712 signatures.

mapping(address /* account */ => uint256) public override authorizationNonces;

Parameters

NameTypeDescription
<none>address

Returns

NameTypeDescription
<none>uint256

Functions​

constructor​

constructor(
address ohm_,
address gohm_,
address staking_,
address kernel_,
address ltvOracle_,
uint96 interestRateWad_,
uint256 minDebtRequired_
) Policy(Kernel(kernel_));

Parameters

NameTypeDescription
ohm_address
gohm_address
staking_address
kernel_address
ltvOracle_address
interestRateWad_uint96
minDebtRequired_uint256

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

Returns

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

setAuthorization​

Sets the authorization for authorized to manage msg.sender's positions until authorizationDeadline

Authorization can be revoked by setting the authorizationDeadline into the past

function setAuthorization(address authorized, uint96 authorizationDeadline) external override;

Parameters

NameTypeDescription
authorizedaddressThe authorized address.
authorizationDeadlineuint96The unix timestamp that they the authorization is valid until.

setAuthorizationWithSig​

Sets the authorization for authorization.authorized to manage authorization.authorizer's positions until authorization.authorizationDeadline.

Warning: Reverts if the signature has already been submitted.

The signature is malleable, but it has no impact on the security here.

The nonce is passed as argument to be able to revert with a different error message.

Authorization can be revoked by calling setAuthorization() and setting the authorizationDeadline into the past

function setAuthorizationWithSig(
Authorization memory authorization,
Signature calldata signature
) external override;

Parameters

NameTypeDescription
authorizationAuthorizationThe Authorization struct.
signatureSignatureThe signature.

isSenderAuthorized​

Returns whether the sender is authorized to manage onBehalf's positions.

function isSenderAuthorized(
address sender,
address onBehalfOf
) public view override returns (bool);

Parameters

NameTypeDescription
senderaddress
onBehalfOfaddress

Returns

NameTypeDescription
<none>bool

_requireSenderAuthorized​

function _requireSenderAuthorized(address sender, address onBehalfOf) internal view;

Parameters

NameTypeDescription
senderaddress
onBehalfOfaddress

addCollateral​

Deposit gOHM as collateral

function addCollateral(
uint128 collateralAmount,
address onBehalfOf,
IDLGTEv1.DelegationRequest[] calldata delegationRequests
) external override;

Parameters

NameTypeDescription
collateralAmountuint128The amount to deposit to 18 decimal places
- MUST be greater than zero
onBehalfOfaddressA caller can add collateral on behalf of themselves or another address.
- MUST NOT be address(0)
delegationRequestsIDLGTEv1.DelegationRequest[]The set of delegations to apply after adding collateral.
- MAY be empty, meaning no delegations are applied.
- MUST ONLY be requests to add delegations, and that total MUST BE less than the collateralAmount argument
- If onBehalfOf does not equal the caller, the caller must be authorized via
setAuthorization() or setAuthorizationWithSig()

withdrawCollateral​

Withdraw gOHM collateral.

  • Account LTV MUST be less than or equal to maxOriginationLtv after the withdraw is applied
  • At least collateralAmount collateral MUST be undelegated for this account. Use the delegationRequests to rescind enough as part of this request.
function withdrawCollateral(
uint128 collateralAmount,
address onBehalfOf,
address recipient,
IDLGTEv1.DelegationRequest[] calldata delegationRequests
) external override returns (uint128 collateralWithdrawn);

Parameters

NameTypeDescription
collateralAmountuint128The amount of collateral to remove to 18 decimal places
- MUST be greater than zero
- If set to type(uint128).max then withdraw the max amount up to maxOriginationLtv
onBehalfOfaddressA caller can withdraw collateral on behalf of themselves or another address if
authorized via setAuthorization() or setAuthorizationWithSig()
recipientaddressSend the gOHM collateral to a specified recipient address.
- MUST NOT be address(0)
delegationRequestsIDLGTEv1.DelegationRequest[]The set of delegations to apply before removing collateral.
- MAY be empty, meaning no delegations are applied.
- MUST ONLY be requests to undelegate, and that total undelegated MUST BE less than the collateralAmount argument

Returns

NameTypeDescription
collateralWithdrawnuint128

borrow​

Borrow debtToken

  • Account LTV MUST be less than or equal to maxOriginationLtv after the borrow is applied
  • Total debt for this account MUST be greater than or equal to the minDebtRequired after the borrow is applied
function borrow(
uint128 borrowAmount,
address onBehalfOf,
address recipient
) external override returns (uint128 amountBorrowed);

Parameters

NameTypeDescription
borrowAmountuint128The amount of debtToken to borrow, to 18 decimals regardless of the debt token
- MUST be greater than zero
- If set to type(uint128).max then borrow the max amount up to maxOriginationLtv
onBehalfOfaddressA caller can borrow on behalf of themselves or another address if
authorized via setAuthorization() or setAuthorizationWithSig()
recipientaddressSend the borrowed token to a specified recipient address.
- MUST NOT be address(0)

Returns

NameTypeDescription
amountBorroweduint128The amount actually borrowed.

repay​

Repay a portion, or all of the debt

  • MUST NOT be called for an account which has no debt
  • If the entire debt isn't paid off, then the total debt for this account MUST be greater than or equal to the minDebtRequired after the borrow is applied
function repay(
uint128 repayAmount,
address onBehalfOf
) external override returns (uint128 amountRepaid);

Parameters

NameTypeDescription
repayAmountuint128The amount to repay, to 18 decimals regardless of the debt token
- MUST be greater than zero
- MAY be greater than the latest debt as of this block. In which case it will be capped
to that latest debt
onBehalfOfaddressA caller can repay the debt on behalf of themselves or another address

Returns

NameTypeDescription
amountRepaiduint128The amount actually repaid.

applyDelegations​

Apply a set of delegation requests on behalf of a given user.

function applyDelegations(
IDLGTEv1.DelegationRequest[] calldata delegationRequests,
address onBehalfOf
)
external
override
returns (uint256 totalDelegated, uint256 totalUndelegated, uint256 undelegatedBalance);

Parameters

NameTypeDescription
delegationRequestsIDLGTEv1.DelegationRequest[]The set of delegations to apply.
- MAY be empty, meaning no delegations are applied.
- Total collateral delegated as part of these requests MUST BE less than the account collateral.
- MUST NOT apply delegations that results in more collateral being undelegated than
the account has collateral for.
- It applies across total gOHM balances for a given account across all calling policies
So this may (un)delegate the account's gOHM set by another policy
onBehalfOfaddressA caller can apply delegations on behalf of themselves or another address if
authorized via setAuthorization() or setAuthorizationWithSig()

Returns

NameTypeDescription
totalDelegateduint256
totalUndelegateduint256
undelegatedBalanceuint256

applyUnhealthyDelegations​

If an account becomes unhealthy and has many delegations such that liquidation can't be performed in one transaction, then delegations can be rescinded over multiple transactions in order to get this account into a state where it can then be liquidated.

function applyUnhealthyDelegations(
address account,
uint256 autoRescindMaxNumDelegates
) external override returns (uint256 totalUndelegated, uint256 undelegatedBalance);

Parameters

NameTypeDescription
accountaddress
autoRescindMaxNumDelegatesuint256

Returns

NameTypeDescription
totalUndelegateduint256
undelegatedBalanceuint256

batchLiquidate​

Liquidate one or more accounts which have exceeded the liquidationLtv The gOHM collateral is seized (unstaked to OHM and burned), and the accounts debt is wiped.

  • If one of the provided accounts in the batch hasn't exceeded the max LTV then it is skipped.
    • Delegations are auto-rescinded if required. Ordering of this is not guaranteed.
function batchLiquidate(
address[] calldata accounts
)
external
override
returns (
uint128 totalCollateralClaimed,
uint128 totalDebtWiped,
uint128 totalLiquidationIncentive
);

Parameters

NameTypeDescription
accountsaddress[]

Returns

NameTypeDescription
totalCollateralClaimeduint128
totalDebtWipeduint128
totalLiquidationIncentiveuint128

setLtvOracle​

Set the oracle which serves the max Origination LTV and the Liquidation LTV

function setLtvOracle(address newOracle) external override onlyAdminRole;

Parameters

NameTypeDescription
newOracleaddress

setTreasuryBorrower​

Set the policy which borrows/repays from Treasury on behalf of Cooler

function setTreasuryBorrower(address newTreasuryBorrower) external override;

Parameters

NameTypeDescription
newTreasuryBorroweraddress

setLiquidationsPaused​

Liquidation may be paused in order for users to recover/repay debt after emergency actions

Can only be called by emergency or admin roles

function setLiquidationsPaused(bool isPaused) external override onlyEmergencyOrAdminRole;

Parameters

NameTypeDescription
isPausedbool

setBorrowPaused​

Pause any new borrows of debtToken

Can only be called by emergency or admin roles

function setBorrowPaused(bool isPaused) external override onlyEmergencyOrAdminRole;

Parameters

NameTypeDescription
isPausedbool

setInterestRateWad​

Update the interest rate (APR), specified in Wad (18 decimals)

  • Cannot be set higher than 10% APR
  • Interest (approximately) continuously compounds at this rate.
function setInterestRateWad(uint96 newInterestRate) external override onlyAdminRole;

Parameters

NameTypeDescription
newInterestRateuint96

setMaxDelegateAddresses​

Allow an account to have more or less than the DEFAULT_MAX_DELEGATE_ADDRESSES number of delegates.

function setMaxDelegateAddresses(
address account,
uint32 maxDelegateAddresses
) external override onlyAdminRole;

Parameters

NameTypeDescription
accountaddress
maxDelegateAddressesuint32

checkpointDebt​

Update and checkpoint the total debt up until now

May be useful in case there are no new user actions for some time.

function checkpointDebt()
external
override
returns (uint128 /*totalDebt*/, uint256 /*interestAccumulatorRay*/);

Returns

NameTypeDescription
<none>uint128
<none>uint256

collateralToken​

The collateral token supplied by users/accounts, eg gOHM

function collateralToken() external view override returns (IERC20);

Returns

NameTypeDescription
<none>IERC20

ohm​

Unwrapped gOHM

function ohm() external view override returns (IERC20);

Returns

NameTypeDescription
<none>IERC20

debtToken​

The debt token which can be borrowed, eg DAI or USDS

function debtToken() external view override returns (IERC20);

Returns

NameTypeDescription
<none>IERC20

staking​

staking contract to unstake (and burn) OHM from liquidations

function staking() external view override returns (IStaking);

Returns

NameTypeDescription
<none>IStaking

minDebtRequired​

The minimum debt a user needs to maintain

It costs gas to liquidate users, so we don't want dust amounts. To 18 decimal places

function minDebtRequired() external view override returns (uint256);

Returns

NameTypeDescription
<none>uint256

loanToValues​

The current Max Origination LTV and Liquidation LTV from the ltvOracle()

Both to 18 decimal places

function loanToValues()
external
view
override
returns (uint96 maxOriginationLtv, uint96 liquidationLtv);

Returns

NameTypeDescription
maxOriginationLtvuint96
liquidationLtvuint96

debtDeltaForMaxOriginationLtv​

Calculate the difference in debt required in order to be at or just under the maxOriginationLTV if collateralDelta was added/removed from the current position. A positive debtDeltaInWad means the account can borrow that amount after adding that collateralDelta collateral A negative debtDeltaInWad means it needs to repay that amount in order to withdraw that collateralDelta collateral

debtDeltaInWad is always to 18 decimal places

function debtDeltaForMaxOriginationLtv(
address account,
int128 collateralDelta
) external view override returns (int128 debtDelta);

Parameters

NameTypeDescription
accountaddress
collateralDeltaint128

Returns

NameTypeDescription
debtDeltaint128

accountPosition​

An view of an accounts current and up to date position as of this block

function accountPosition(
address account
) external view override returns (AccountPosition memory position);

Parameters

NameTypeDescription
accountaddressThe account to get a position for

Returns

NameTypeDescription
positionAccountPosition

computeLiquidity​

Compute the liquidity status for a set of accounts.

This can be used to verify if accounts can be liquidated or not.

function computeLiquidity(
address[] calldata accounts
) external view override returns (LiquidationStatus[] memory status);

Parameters

NameTypeDescription
accountsaddress[]The accounts to get the status for.

Returns

NameTypeDescription
statusLiquidationStatus[]

accountDelegationsList​

Paginated view of an account's delegations

Can call sequentially increasing the startIndex each time by the number of items returned in the previous call, until number of items returned is less than maxItems

function accountDelegationsList(
address account,
uint256 startIndex,
uint256 maxItems
) external view override returns (IDLGTEv1.AccountDelegation[] memory delegations);

Parameters

NameTypeDescription
accountaddress
startIndexuint256
maxItemsuint256

Returns

NameTypeDescription
delegationsIDLGTEv1.AccountDelegation[]

accountState​

A view of the last checkpoint of account data (not as of this block)

function accountState(address account) external view override returns (AccountState memory);

Parameters

NameTypeDescription
accountaddress

Returns

NameTypeDescription
<none>AccountState

accountCollateral​

An account's current collateral

to 18 decimal places

function accountCollateral(address account) external view override returns (uint128);

Parameters

NameTypeDescription
accountaddress

Returns

NameTypeDescription
<none>uint128

accountDebt​

An account's current debt as of this block

function accountDebt(address account) external view override returns (uint128);

Parameters

NameTypeDescription
accountaddress

Returns

NameTypeDescription
<none>uint128

globalState​

A view of the derived/internal cache data.

function globalState()
external
view
override
returns (uint128 /*totalDebt*/, uint256 /*interestAccumulatorRay*/);

Returns

NameTypeDescription
<none>uint128
<none>uint256

_globalStateRW​

Setup and refresh the global state Update storage if and only if the timestamp has changed since last updated.

function _globalStateRW() private returns (GlobalStateCache memory gStateCache);

Returns

NameTypeDescription
gStateCacheGlobalStateCache

_globalStateRO​

Setup the GlobalStateCache for a given token read only -- storage isn't updated.

function _globalStateRO() private view returns (GlobalStateCache memory gStateCache);

Returns

NameTypeDescription
gStateCacheGlobalStateCache

_initGlobalStateCache​

Initialize the global state cache from storage to this block, for a given token.

function _initGlobalStateCache(
GlobalStateCache memory gStateCache
) private view returns (bool dirty);

Parameters

NameTypeDescription
gStateCacheGlobalStateCache

Returns

NameTypeDescription
dirtybool

_reduceTotalDebt​

Reduce the total debt in storage by a repayment amount. NB: The sum of all users debt may be slightly more than the recorded total debt because users debt is rounded up for dust. The total debt is floored at 0.

function _reduceTotalDebt(GlobalStateCache memory gStateCache, uint128 repayAmount) private;

Parameters

NameTypeDescription
gStateCacheGlobalStateCache
repayAmountuint128

_maxDebt​

Calculate the maximum amount which can be borrowed up to the maxOriginationLtv, given a collateral amount

function _maxDebt(
uint128 collateral,
uint256 maxOriginationLtv
) private pure returns (uint128);

Parameters

NameTypeDescription
collateraluint128
maxOriginationLtvuint256

Returns

NameTypeDescription
<none>uint128

_minCollateral​

Calculate the maximum collateral amount which can be withdrawn up to the maxOriginationLtv, given a current debt amount

function _minCollateral(
uint128 debt,
uint256 maxOriginationLtv
) private pure returns (uint128);

Parameters

NameTypeDescription
debtuint128
maxOriginationLtvuint256

Returns

NameTypeDescription
<none>uint128

_validateOriginationLtv​

Ensure the LTV isn't higher than the maxOriginationLtv

function _validateOriginationLtv(uint128 ltv, uint256 maxOriginationLtv) private pure;

Parameters

NameTypeDescription
ltvuint128
maxOriginationLtvuint256

_calculateCurrentLtv​

Calculate the current LTV based on the latest debt

function _calculateCurrentLtv(
uint128 currentDebt,
uint128 collateral
) private pure returns (uint128);

Parameters

NameTypeDescription
currentDebtuint128
collateraluint128

Returns

NameTypeDescription
<none>uint128

_computeLiquidity​

Generate the LiquidationStatus struct with current details for this account.

function _computeLiquidity(
AccountState memory aStateCache,
GlobalStateCache memory gStateCache
) private pure returns (LiquidationStatus memory status);

Parameters

NameTypeDescription
aStateCacheAccountState
gStateCacheGlobalStateCache

Returns

NameTypeDescription
statusLiquidationStatus

_currentAccountDebt​

Calculate the latest debt for a given account & token. Derived from the prior debt checkpoint, and the interest accumulator.

function _currentAccountDebt(
uint128 accountDebtCheckpoint_,
uint256 accountInterestAccumulatorRay_,
uint256 globalInterestAccumulatorRay_
) private pure returns (uint128 result);

Parameters

NameTypeDescription
accountDebtCheckpoint_uint128
accountInterestAccumulatorRay_uint256
globalInterestAccumulatorRay_uint256

Returns

NameTypeDescription
resultuint128

_requireAmountNonZero​

function _requireAmountNonZero(uint256 amount_) internal pure;

Parameters

NameTypeDescription
amount_uint256

_requireAddressNonZero​

function _requireAddressNonZero(address addr_) internal pure;

Parameters

NameTypeDescription
addr_address

Structs​

GlobalStateCache​

struct GlobalStateCache {
/**
* @notice The total amount that has already been borrowed by all accounts.
* This increases as interest accrues or new borrows.
* Decreases on repays or liquidations.
*/
uint128 totalDebt;
/**
* @notice Internal tracking of the accumulated interest as an index starting from 1.0e27
* When this accumulator is compunded by the interest rate, the total debt can be calculated as
* `updatedTotalDebt = prevTotalDebt * latestInterestAccumulator / prevInterestAccumulator
*/
uint256 interestAccumulatorRay;
/**
* @notice The current Liquidation LTV, served from the `ltvOracle`
*/
uint96 liquidationLtv;
/**
* @notice The current Max Origination LTV, served from the `ltvOracle`
*/
uint96 maxOriginationLtv;
}

Properties

NameTypeDescription
totalDebtuint128
interestAccumulatorRayuint256
liquidationLtvuint96
maxOriginationLtvuint96