cove-contracts-core

cove

codecov CI Discord X (formerly Twitter) Follow

This repository contains the core smart contracts for the Cove Protocol.

The testing suite includes unit, integration, fork, and invariant tests.

For more detailed information, visit the documentation or the technical RFC.

[!IMPORTANT] You acknowledge that there are potential uses of the [Licensed Work] that could be deemed illegal or noncompliant under U.S. law. You agree that you will not use the [Licensed Work] for any activities that are or may reasonably be expected to be deemed illegal or noncompliant under U.S. law. You also agree that you, and not [Storm Labs], are responsible for any illegal or noncompliant uses of the [Licensed Work] that you facilitate, enable, engage in, support, promote, or are otherwise involved with.

Prerequisites

Ensure you have the following installed:

Installation

Setup pyenv and install the python dependencies:

pyenv install 3.9.17
pyenv virtualenv 3.9.17 cove-contracts-core
pyenv local cove-contracts-core
pip install -r requirements.txt

Install node and build dependencies:

# Install node dependencies
pnpm install
# Install submodules as soldeer dependencies
forge soldeer install

Usage

Build the contracts:

pnpm build

Run the tests:

pnpm test

Run slither static analysis

Install slither and run the tool:

pnpm slither

To run the upgradeability checks with slither-check-upgradeability:

pnpm slither-upgradeability

Run semgrep static analysis

Install semgrep and run the tool:

pnpm semgrep

Deploying contracts to live network

Local mainnet fork

# Run a fork network using anvil
anvil --rpc-url <fork_network_rpc_url>

Keep this terminal session going to keep the fork network alive.

Then in another terminal session:

# Deploy contracts to local fork network
pnpm localDeploy
  • Deployments will be in deployments/<chainId>-fork.
  • Make sure not to commit broadcast/.
  • If trying to deploy a new contract, either use the default deployer functions or generate them with: $ ./forge-deploy gen-deployer.

Contract Architecture

architecture

Audits

Smart contract audits of the Cove Protocol are available here.

Contents

Contents

GPv2Order

Git Source

Author: Gnosis Developers

State Variables

TYPE_HASH

*The order EIP-712 type hash for the [GPv2Order.Data] struct. This value is pre-computed from the following expression:

keccak256(
"Order(" +
"address sellToken," +
"address buyToken," +
"address receiver," +
"uint256 sellAmount," +
"uint256 buyAmount," +
"uint32 validTo," +
"bytes32 appData," +
"uint256 feeAmount," +
"string kind," +
"bool partiallyFillable," +
"string sellTokenBalance," +
"string buyTokenBalance" +
")"
)
```*


```solidity
bytes32 internal constant TYPE_HASH = hex"d5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e489";

KIND_SELL

*The marker value for a sell order for computing the order struct hash. This allows the EIP-712 compatible wallets to display a descriptive string for the order kind (instead of 0 or 1). This value is pre-computed from the following expression:

keccak256("sell")
```*


```solidity
bytes32 internal constant KIND_SELL = hex"f3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee346775";

KIND_BUY

*The OrderKind marker value for a buy order for computing the order struct hash. This value is pre-computed from the following expression:

keccak256("buy")
```*


```solidity
bytes32 internal constant KIND_BUY = hex"6ed88e868af0a1983e3886d5f3e95a2fafbd6c3450bc229e27342283dc429ccc";

BALANCE_ERC20

*The TokenBalance marker value for using direct ERC20 balances for computing the order struct hash. This value is pre-computed from the following expression:

keccak256("erc20")
```*


```solidity
bytes32 internal constant BALANCE_ERC20 = hex"5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9";

BALANCE_EXTERNAL

*The TokenBalance marker value for using Balancer Vault external balances (in order to re-use Vault ERC20 approvals) for computing the order struct hash. This value is pre-computed from the following expression:

keccak256("external")
```*


```solidity
bytes32 internal constant BALANCE_EXTERNAL = hex"abee3b73373acd583a130924aad6dc38cfdc44ba0555ba94ce2ff63980ea0632";

BALANCE_INTERNAL

*The TokenBalance marker value for using Balancer Vault internal balances for computing the order struct hash. This value is pre-computed from the following expression:

keccak256("internal")
```*


```solidity
bytes32 internal constant BALANCE_INTERNAL = hex"4ac99ace14ee0a5ef932dc609df0943ab7ac16b7583634612f8dc35a4289a6ce";

RECEIVER_SAME_AS_OWNER

Marker address used to indicate that the receiver of the trade proceeds should the owner of the order. This is chosen to be address(0) for gas efficiency as it is expected to be the most common case.

address internal constant RECEIVER_SAME_AS_OWNER = address(0);

UID_LENGTH

The byte length of an order unique identifier.

uint256 internal constant UID_LENGTH = 56;

Functions

actualReceiver

Returns the actual receiver for an order. This function checks whether or not the [receiver] field uses the marker value to indicate it is the same as the order owner.

function actualReceiver(Data memory order, address owner) internal pure returns (address receiver);

Returns

NameTypeDescription
receiveraddressThe actual receiver of trade proceeds.

hash

Return the EIP-712 signing hash for the specified order.

function hash(Data memory order, bytes32 domainSeparator) internal pure returns (bytes32 orderDigest);

Parameters

NameTypeDescription
orderDataThe order to compute the EIP-712 signing hash for.
domainSeparatorbytes32The EIP-712 domain separator to use.

Returns

NameTypeDescription
orderDigestbytes32The 32 byte EIP-712 struct hash.

packOrderUidParams

Packs order UID parameters into the specified memory location. The result is equivalent to abi.encodePacked(...) with the difference that it allows re-using the memory for packing the order UID. This function reverts if the order UID buffer is not the correct size.

function packOrderUidParams(bytes memory orderUid, bytes32 orderDigest, address owner, uint32 validTo) internal pure;

Parameters

NameTypeDescription
orderUidbytesThe buffer pack the order UID parameters into.
orderDigestbytes32The EIP-712 struct digest derived from the order parameters.
owneraddressThe address of the user who owns this order.
validTouint32The epoch time at which the order will stop being valid.

extractOrderUidParams

Extracts specific order information from the standardized unique order id of the protocol.

function extractOrderUidParams(bytes calldata orderUid)
    internal
    pure
    returns (bytes32 orderDigest, address owner, uint32 validTo);

Parameters

NameTypeDescription
orderUidbytesThe unique identifier used to represent an order in the protocol. This uid is the packed concatenation of the order digest, the validTo order parameter and the address of the user who created the order. It is used by the user to interface with the contract directly, and not by calls that are triggered by the solvers.

Returns

NameTypeDescription
orderDigestbytes32The EIP-712 signing digest derived from the order parameters.
owneraddressThe address of the user who owns this order.
validTouint32The epoch time at which the order will stop being valid.

Structs

Data

The complete data for a Gnosis Protocol order. This struct contains all order parameters that are signed for submitting to GP.

struct Data {
    IERC20 sellToken;
    IERC20 buyToken;
    address receiver;
    uint256 sellAmount;
    uint256 buyAmount;
    uint32 validTo;
    bytes32 appData;
    uint256 feeAmount;
    bytes32 kind;
    bool partiallyFillable;
    bytes32 sellTokenBalance;
    bytes32 buyTokenBalance;
}

Contents

Contents

SelfPermit

Git Source

Inherits: ISelfPermit

Functionality to call permit on any EIP-2612-compliant token for use in the route

These functions are expected to be embedded in multicalls to allow EOAs to approve a contract and call a function that requires an approval in a single transaction.

Functions

selfPermit

Permits this contract to spend a given token from msg.sender

The owner is always msg.sender and the spender is always address(this).

function selfPermit(
    address token,
    uint256 value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
)
    public
    payable
    override;

Parameters

NameTypeDescription
tokenaddressThe address of the token spent
valueuint256The amount that can be spent of token
deadlineuint256A timestamp, the current blocktime must be less than or equal to this timestamp
vuint8Must produce valid secp256k1 signature from the holder along with r and s
rbytes32Must produce valid secp256k1 signature from the holder along with v and s
sbytes32Must produce valid secp256k1 signature from the holder along with r and v

selfPermitIfNecessary

Permits this contract to spend a given token from msg.sender

The owner is always msg.sender and the spender is always address(this). Can be used instead of #selfPermit to prevent calls from failing due to a frontrun of a call to #selfPermit

function selfPermitIfNecessary(
    address token,
    uint256 value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
)
    external
    payable
    override;

Parameters

NameTypeDescription
tokenaddressThe address of the token spent
valueuint256The amount that can be spent of token
deadlineuint256A timestamp, the current blocktime must be less than or equal to this timestamp
vuint8Must produce valid secp256k1 signature from the holder along with r and s
rbytes32Must produce valid secp256k1 signature from the holder along with v and s
sbytes32Must produce valid secp256k1 signature from the holder along with r and v

selfPermitAllowed

Permits this contract to spend the sender's tokens for permit signatures that have the allowed parameter

The owner is always msg.sender and the spender is always address(this)

function selfPermitAllowed(
    address token,
    uint256 nonce,
    uint256 expiry,
    uint8 v,
    bytes32 r,
    bytes32 s
)
    public
    payable
    override;

Parameters

NameTypeDescription
tokenaddressThe address of the token spent
nonceuint256The current nonce of the owner
expiryuint256The timestamp at which the permit is no longer valid
vuint8Must produce valid secp256k1 signature from the holder along with r and s
rbytes32Must produce valid secp256k1 signature from the holder along with v and s
sbytes32Must produce valid secp256k1 signature from the holder along with r and v

selfPermitAllowedIfNecessary

Permits this contract to spend the sender's tokens for permit signatures that have the allowed parameter

The owner is always msg.sender and the spender is always address(this) Can be used instead of #selfPermitAllowed to prevent calls from failing due to a frontrun of a call to #selfPermitAllowed.

function selfPermitAllowedIfNecessary(
    address token,
    uint256 nonce,
    uint256 expiry,
    uint8 v,
    bytes32 r,
    bytes32 s
)
    external
    payable
    override;

Parameters

NameTypeDescription
tokenaddressThe address of the token spent
nonceuint256The current nonce of the owner
expiryuint256The timestamp at which the permit is no longer valid
vuint8Must produce valid secp256k1 signature from the holder along with r and s
rbytes32Must produce valid secp256k1 signature from the holder along with v and s
sbytes32Must produce valid secp256k1 signature from the holder along with r and v

Contents

Contents

IERC20PermitAllowed

Git Source

Interface used by DAI/CHAI for permit

Functions

permit

Approve the spender to spend some tokens via the holder signature

This is the permit interface used by DAI and CHAI

function permit(
    address holder,
    address spender,
    uint256 nonce,
    uint256 expiry,
    bool allowed,
    uint8 v,
    bytes32 r,
    bytes32 s
)
    external;

Parameters

NameTypeDescription
holderaddressThe address of the token holder, the token owner
spenderaddressThe address of the token spender
nonceuint256The holder's nonce, increases at each call to permit
expiryuint256The timestamp at which the permit is no longer valid
allowedboolBoolean that sets approval amount, true for type(uint256).max and false for 0
vuint8Must produce valid secp256k1 signature from the holder along with r and s
rbytes32Must produce valid secp256k1 signature from the holder along with v and s
sbytes32Must produce valid secp256k1 signature from the holder along with r and v

ISelfPermit

Git Source

Functionality to call permit on any EIP-2612-compliant token for use in the route

Functions

selfPermit

Permits this contract to spend a given token from msg.sender

The owner is always msg.sender and the spender is always address(this).

function selfPermit(address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external payable;

Parameters

NameTypeDescription
tokenaddressThe address of the token spent
valueuint256The amount that can be spent of token
deadlineuint256A timestamp, the current blocktime must be less than or equal to this timestamp
vuint8Must produce valid secp256k1 signature from the holder along with r and s
rbytes32Must produce valid secp256k1 signature from the holder along with v and s
sbytes32Must produce valid secp256k1 signature from the holder along with r and v

selfPermitIfNecessary

Permits this contract to spend a given token from msg.sender

The owner is always msg.sender and the spender is always address(this). Can be used instead of #selfPermit to prevent calls from failing due to a frontrun of a call to #selfPermit

function selfPermitIfNecessary(
    address token,
    uint256 value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
)
    external
    payable;

Parameters

NameTypeDescription
tokenaddressThe address of the token spent
valueuint256The amount that can be spent of token
deadlineuint256A timestamp, the current blocktime must be less than or equal to this timestamp
vuint8Must produce valid secp256k1 signature from the holder along with r and s
rbytes32Must produce valid secp256k1 signature from the holder along with v and s
sbytes32Must produce valid secp256k1 signature from the holder along with r and v

selfPermitAllowed

Permits this contract to spend the sender's tokens for permit signatures that have the allowed parameter

The owner is always msg.sender and the spender is always address(this)

function selfPermitAllowed(
    address token,
    uint256 nonce,
    uint256 expiry,
    uint8 v,
    bytes32 r,
    bytes32 s
)
    external
    payable;

Parameters

NameTypeDescription
tokenaddressThe address of the token spent
nonceuint256The current nonce of the owner
expiryuint256The timestamp at which the permit is no longer valid
vuint8Must produce valid secp256k1 signature from the holder along with r and s
rbytes32Must produce valid secp256k1 signature from the holder along with v and s
sbytes32Must produce valid secp256k1 signature from the holder along with r and v

selfPermitAllowedIfNecessary

Permits this contract to spend the sender's tokens for permit signatures that have the allowed parameter

The owner is always msg.sender and the spender is always address(this) Can be used instead of #selfPermitAllowed to prevent calls from failing due to a frontrun of a call to #selfPermitAllowed.

function selfPermitAllowedIfNecessary(
    address token,
    uint256 nonce,
    uint256 expiry,
    uint8 v,
    bytes32 r,
    bytes32 s
)
    external
    payable;

Parameters

NameTypeDescription
tokenaddressThe address of the token spent
nonceuint256The current nonce of the owner
expiryuint256The timestamp at which the permit is no longer valid
vuint8Must produce valid secp256k1 signature from the holder along with r and s
rbytes32Must produce valid secp256k1 signature from the holder along with v and s
sbytes32Must produce valid secp256k1 signature from the holder along with r and v

Contents

Contents

IChainlinkAggregatorV3Interface

Git Source

Functions

decimals

function decimals() external view returns (uint8);

description

function description() external view returns (string memory);

version

function version() external view returns (uint256);

getRoundData

function getRoundData(uint80 _roundId)
    external
    view
    returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);

latestRoundData

function latestRoundData()
    external
    view
    returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);

IPyth

Git Source

Functions

updatePriceFeeds

Update price feeds with given update messages. This method requires the caller to pay a fee in wei; the required fee can be computed by calling getUpdateFee with the length of the updateData array. Prices will be updated if they are more recent than the current stored prices. The call will succeed even if the update is not the most recent.

Reverts if the transferred fee is not sufficient or the updateData is invalid.

function updatePriceFeeds(bytes[] calldata updateData) external payable;

Parameters

NameTypeDescription
updateDatabytes[]Array of price update data.

getUpdateFee

Returns the required fee to update an array of price updates.

function getUpdateFee(bytes[] calldata updateData) external view returns (uint256 feeAmount);

Parameters

NameTypeDescription
updateDatabytes[]Array of price update data.

Returns

NameTypeDescription
feeAmountuint256The required fee in Wei.

getPrice

Returns the price and confidence interval.

Reverts if the price has not been updated within the last getValidTimePeriod() seconds.

function getPrice(bytes32 id) external view returns (Price memory price);

Parameters

NameTypeDescription
idbytes32The Pyth Price Feed ID of which to fetch the price and confidence interval.

Returns

NameTypeDescription
pricePrice- please read the documentation of PythStructs.Price to understand how to use this safely.

Structs

Price

struct Price {
    int64 price;
    uint64 conf;
    int32 expo;
    uint256 publishTime;
}

PriceFeed

struct PriceFeed {
    bytes32 id;
    Price price;
    Price emaPrice;
}

IAllocationResolver

Git Source

Functions

setAllocation

function setAllocation(address basket, bytes32[] calldata newAllocation) external;

getTargetWeight

function getTargetWeight(address basket) external view returns (bytes32[] memory);

getAllocationLength

function getAllocationLength(address basket) external view returns (uint256);

getAllocationElement

function getAllocationElement(address basket, uint256 index) external view returns (bytes32);

setBasketResolver

function setBasketResolver(address basket, address resolver) external;

enroll

function enroll(address basket, address resolver, uint256 selectionsLength) external;

isEnrolled

function isEnrolled(address basket) external view returns (bool);

isSubscribed

function isSubscribed(address basket, address proposer) external view returns (bool);

IERC7540Operator

Git Source

Functions

setOperator

Sets or removes an operator for the caller.

function setOperator(address operator, bool approved) external returns (bool);

Parameters

NameTypeDescription
operatoraddressThe address of the operator.
approvedboolThe approval status.

Returns

NameTypeDescription
<none>boolWhether the call was executed successfully or not

isOperator

Returns true if the operator is approved as an operator for an controller.

function isOperator(address controller, address operator) external view returns (bool status);

Parameters

NameTypeDescription
controlleraddressThe address of the controller.
operatoraddressThe address of the operator.

Returns

NameTypeDescription
statusboolThe approval status

Events

OperatorSet

The event emitted when an operator is set.

event OperatorSet(address indexed controller, address indexed operator, bool approved);

Parameters

NameTypeDescription
controlleraddressThe address of the controller.
operatoraddressThe address of the operator.
approvedboolThe approval status.

IERC7540Deposit

Git Source

Functions

requestDeposit

*Transfers assets from sender into the Vault and submits a Request for asynchronous deposit.

  • MUST support ERC-20 approve / transferFrom on asset as a deposit Request flow.
  • MUST revert if all of assets cannot be requested for deposit.
  • owner MUST be msg.sender unless some unspecified explicit approval is given by the caller, approval of ERC-20 tokens from owner to sender is NOT enough.*
function requestDeposit(uint256 assets, address controller, address owner) external returns (uint256 requestId);

Parameters

NameTypeDescription
assetsuint256the amount of deposit assets to transfer from owner
controlleraddressthe controller of the request who will be able to operate the request
owneraddressthe source of the deposit assets NOTE: most implementations will require pre-approval of the Vault with the Vault's underlying asset token.

pendingDepositRequest

*Returns the amount of requested assets in Pending state.

  • MUST NOT include any assets in Claimable state for deposit or mint.
  • MUST NOT show any variations depending on the caller.
  • MUST NOT revert unless due to integer overflow caused by an unreasonably large input.*
function pendingDepositRequest(uint256 requestId, address controller) external view returns (uint256 pendingAssets);

claimableDepositRequest

*Returns the amount of requested assets in Claimable state for the controller to deposit or mint.

  • MUST NOT include any assets in Pending state.
  • MUST NOT show any variations depending on the caller.
  • MUST NOT revert unless due to integer overflow caused by an unreasonably large input.*
function claimableDepositRequest(
    uint256 requestId,
    address controller
)
    external
    view
    returns (uint256 claimableAssets);

deposit

*Mints shares Vault shares to receiver by claiming the Request of the controller.

  • MUST emit the Deposit event.
  • controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.*
function deposit(uint256 assets, address receiver, address controller) external returns (uint256 shares);

mint

*Mints exactly shares Vault shares to receiver by claiming the Request of the controller.

  • MUST emit the Deposit event.
  • controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.*
function mint(uint256 shares, address receiver, address controller) external returns (uint256 assets);

Events

DepositRequest

event DepositRequest(
    address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
);

IERC7540Redeem

Git Source

Functions

requestRedeem

*Assumes control of shares from sender into the Vault and submits a Request for asynchronous redeem.

  • MUST support a redeem Request flow where the control of shares is taken from sender directly where msg.sender has ERC-20 approval over the shares of owner.
  • MUST revert if all of shares cannot be requested for redeem.*
function requestRedeem(uint256 shares, address controller, address owner) external returns (uint256 requestId);

Parameters

NameTypeDescription
sharesuint256the amount of shares to be redeemed to transfer from owner
controlleraddressthe controller of the request who will be able to operate the request
owneraddressthe source of the shares to be redeemed NOTE: most implementations will require pre-approval of the Vault with the Vault's share token.

pendingRedeemRequest

*Returns the amount of requested shares in Pending state.

  • MUST NOT include any shares in Claimable state for redeem or withdraw.
  • MUST NOT show any variations depending on the caller.
  • MUST NOT revert unless due to integer overflow caused by an unreasonably large input.*
function pendingRedeemRequest(uint256 requestId, address controller) external view returns (uint256 pendingShares);

claimableRedeemRequest

*Returns the amount of requested shares in Claimable state for the controller to redeem or withdraw.

  • MUST NOT include any shares in Pending state for redeem or withdraw.
  • MUST NOT show any variations depending on the caller.
  • MUST NOT revert unless due to integer overflow caused by an unreasonably large input.*
function claimableRedeemRequest(
    uint256 requestId,
    address controller
)
    external
    view
    returns (uint256 claimableShares);

Events

RedeemRequest

event RedeemRequest(
    address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
);

IERC7575

Git Source

Inherits: IERC165

Functions

asset

*Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.

  • MUST be an ERC-20 token contract.
  • MUST NOT revert.*
function asset() external view returns (address assetTokenAddress);

share

*Returns the address of the share token

  • MUST be an ERC-20 token contract.
  • MUST NOT revert.*
function share() external view returns (address shareTokenAddress);

convertToShares

*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.

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

convertToAssets

*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.

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

totalAssets

*Returns the total amount of the underlying asset that is “managed” by Vault.

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

maxDeposit

*Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver, through a deposit call.

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

previewDeposit

*Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given current on-chain conditions.

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

deposit

*Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.

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

maxMint

*Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.

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

previewMint

*Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given current on-chain conditions.

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

mint

*Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.

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

maxWithdraw

*Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the Vault, through a withdraw call.

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

previewWithdraw

*Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, given current on-chain conditions.

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

withdraw

*Burns shares from owner and sends exactly assets of underlying tokens to receiver.

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

maxRedeem

*Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault, through a redeem call.

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

previewRedeem

*Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, given current on-chain conditions.

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

redeem

*Burns exactly shares from owner and sends assets of underlying tokens to receiver.

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

Events

Deposit

event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);

Withdraw

event Withdraw(address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares);

Contents

BasketManagerUtils

Git Source

Library containing utility functions for managing storage related to baskets, including creating new baskets, proposing and executing rebalances, and settling internal and external token trades.

State Variables

_USD_ISO_4217_CODE

CONSTANTS ///

ISO 4217 numeric code for USD, used as a constant address representation

address private constant _USD_ISO_4217_CODE = address(840);

_MAX_NUM_OF_BASKET_TOKENS

Maximum number of basket tokens allowed to be created.

uint256 private constant _MAX_NUM_OF_BASKET_TOKENS = 256;

_MAX_SLIPPAGE

Maximum slippage multiplier for token swaps, expressed in 1e18.

uint256 private constant _MAX_SLIPPAGE = 0.05e18;

_MAX_WEIGHT_DEVIATION

Maximum deviation multiplier to determine if a set of balances has reached the desired target weights.

uint256 private constant _MAX_WEIGHT_DEVIATION = 0.05e18;

_WEIGHT_PRECISION

Precision used for weight calculations and slippage calculations.

uint256 private constant _WEIGHT_PRECISION = 1e18;

_MAX_RETRIES

Maximum number of retries for a rebalance.

uint8 private constant _MAX_RETRIES = 3;

_REBALANCE_COOLDOWN_SEC

Minimum time between rebalances in seconds.

uint40 private constant _REBALANCE_COOLDOWN_SEC = 1 hours;

Functions

createNewBasket

Creates a new basket token with the given parameters.

function createNewBasket(
    BasketManagerStorage storage self,
    string calldata basketName,
    string calldata symbol,
    address baseAsset,
    uint256 bitFlag,
    address strategy
)
    external
    returns (address basket);

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
basketNamestringName of the basket.
symbolstringSymbol of the basket.
baseAssetaddress
bitFlaguint256Asset selection bitFlag for the basket.
strategyaddressAddress of the strategy contract for the basket.

Returns

NameTypeDescription
basketaddressAddress of the newly created basket token.

proposeRebalance

Proposes a rebalance for the given baskets. The rebalance is proposed if the difference between the target balance and the current balance of any asset in the basket is more than 500 USD.

function proposeRebalance(BasketManagerStorage storage self, address[] calldata baskets) external;

Parameters

NameTypeDescription
selfBasketManagerStorage
basketsaddress[]Array of basket addresses to rebalance.

proposeTokenSwap

If the proposed token swap results are not close to the target balances, this function will revert.

This function can only be called after proposeRebalance.

function proposeTokenSwap(
    BasketManagerStorage storage self,
    InternalTrade[] calldata internalTrades,
    ExternalTrade[] calldata externalTrades,
    address[] calldata baskets,
    uint64[][] calldata basketTargetWeights
)
    external;

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
internalTradesInternalTrade[]Array of internal trades to execute.
externalTradesExternalTrade[]Array of external trades to execute.
basketsaddress[]Array of basket addresses currently being rebalanced.
basketTargetWeightsuint64[][]Array of target weights for each basket.

completeRebalance

Completes the rebalance for the given baskets. The rebalance can be completed if it has been more than 15 minutes since the last action.

function completeRebalance(
    BasketManagerStorage storage self,
    ExternalTrade[] calldata externalTrades,
    address[] calldata baskets,
    uint64[][] calldata basketTargetWeights
)
    external;

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
externalTradesExternalTrade[]Array of external trades matching those proposed for rebalance.
basketsaddress[]Array of basket addresses proposed for rebalance.
basketTargetWeightsuint64[][]Array of target weights for each basket.

proRataRedeem

FALLBACK REDEEM LOGIC ///

Fallback redeem function to redeem shares when the rebalance is not in progress. Redeems the shares for each underlying asset in the basket pro-rata to the amount of shares redeemed.

function proRataRedeem(
    BasketManagerStorage storage self,
    uint256 totalSupplyBefore,
    uint256 burnedShares,
    address to
)
    external;

Parameters

NameTypeDescription
selfBasketManagerStorage
totalSupplyBeforeuint256Total supply of the basket token before the shares were burned.
burnedSharesuint256Amount of shares burned.
toaddressAddress to send the redeemed assets to.

basketTokenToRebalanceAssetToIndex

Returns the index of the asset in a given basket

function basketTokenToRebalanceAssetToIndex(
    BasketManagerStorage storage self,
    address basketToken,
    address asset
)
    public
    view
    returns (uint256 index);

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
basketTokenaddressBasket token address.
assetaddressAsset address.

Returns

NameTypeDescription
indexuint256Index of the asset in the basket.

basketTokenToIndex

Returns the index of the basket token.

function basketTokenToIndex(
    BasketManagerStorage storage self,
    address basketToken
)
    public
    view
    returns (uint256 index);

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
basketTokenaddressBasket token address.

Returns

NameTypeDescription
indexuint256Index of the basket token.

_indexOf

INTERNAL FUNCTIONS ///

Returns the index of the element in the array.

Reverts if the element does not exist in the array.

function _indexOf(address[] memory array, address element) internal pure returns (uint256 index);

Parameters

NameTypeDescription
arrayaddress[]Array to find the element in.
elementaddressElement to find in the array.

Returns

NameTypeDescription
indexuint256Index of the element in the array.

_finalizeRebalance

PRIVATE FUNCTIONS ///

Internal function to finalize the state changes for the current rebalance. Resets rebalance status and attempts to process pending redeems. If all pending redeems cannot be fulfilled notifies basket token of a failed rebalance.

function _finalizeRebalance(BasketManagerStorage storage self, address[] calldata baskets) private;

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
basketsaddress[]Array of basket addresses currently being rebalanced.

_completeTokenSwap

Internal function to complete proposed token swaps.

function _completeTokenSwap(
    BasketManagerStorage storage self,
    ExternalTrade[] calldata externalTrades
)
    private
    returns (uint256[2][] memory claimedAmounts);

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
externalTradesExternalTrade[]Array of external trades to be completed.

Returns

NameTypeDescription
claimedAmountsuint256[2][]amounts claimed from the completed token swaps

_processExternalTrades

Internal function to update internal accounting with result of completed token swaps.

function _processExternalTrades(BasketManagerStorage storage self, ExternalTrade[] calldata externalTrades) private;

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
externalTradesExternalTrade[]Array of external trades to be completed.

_initializeBasketData

Internal function to initialize basket data.

function _initializeBasketData(
    BasketManagerStorage storage self,
    address[] calldata baskets,
    uint256[][] memory basketBalances,
    uint256[] memory totalValue_
)
    private
    view;

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
basketsaddress[]Array of basket addresses currently being rebalanced.
basketBalancesuint256[][]An empty array used for asset balances for each basket being rebalanced. Updated with current balances at the end of the function.
totalValue_uint256[]An initialized array of total basket values for each basket being rebalanced.

_processInternalTrades

Internal function to settle internal trades.

If the result of an internal trade is not within the provided minAmount or maxAmount, this function will revert.

function _processInternalTrades(
    BasketManagerStorage storage self,
    InternalTrade[] calldata internalTrades,
    address[] calldata baskets,
    uint256[][] memory basketBalances
)
    private;

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
internalTradesInternalTrade[]Array of internal trades to execute.
basketsaddress[]Array of basket addresses currently being rebalanced.
basketBalancesuint256[][]An initialized array of asset amounts for each basket being rebalanced. Updated with settled internal trades at the end of the function.

_validateExternalTrades

Internal function to validate the results of external trades.

If the result of an external trade is not within the _MAX_SLIPPAGE threshold of the minAmount, this function will revert.

function _validateExternalTrades(
    BasketManagerStorage storage self,
    ExternalTrade[] calldata externalTrades,
    address[] calldata baskets,
    uint256[] memory totalValue_,
    uint256[][] memory afterTradeAmounts_
)
    private
    view;

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
externalTradesExternalTrade[]Array of external trades to be validated.
basketsaddress[]Array of basket addresses currently being rebalanced.
totalValue_uint256[]Array of total basket values in USD.
afterTradeAmounts_uint256[][]An initialized array of asset amounts for each basket being rebalanced.

_validateBasketHash

Validate the basket hash based on the given baskets and target weights.

function _validateBasketHash(
    BasketManagerStorage storage self,
    address[] calldata baskets,
    uint64[][] calldata basketsTargetWeights
)
    private
    view;

_isTargetWeightMet

Checks if weight deviations after trades are within the acceptable _MAX_WEIGHT_DEVIATION threshold. Returns true if all deviations are within bounds for each asset in every basket.

function _isTargetWeightMet(
    BasketManagerStorage storage self,
    address[] calldata baskets,
    uint256[][] memory basketBalances,
    uint256[] memory totalValues,
    uint64[][] calldata basketsTargetWeights
)
    private
    view
    returns (bool);

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
basketsaddress[]Array of basket addresses currently being rebalanced.
basketBalancesuint256[][]2D array of asset balances for each basket. Rows are baskets, columns are assets.
totalValuesuint256[]Array of total basket values in USD.
basketsTargetWeightsuint64[][]Array of target weights for each basket.

_processPendingDeposits

Internal function to process pending deposits and fulfill them.

function _processPendingDeposits(
    BasketManagerStorage storage self,
    address basket,
    uint256 basketValue,
    uint256 baseAssetBalance,
    uint256 pendingDeposit,
    uint256 baseAssetIndex
)
    private
    returns (uint256 totalSupply, uint256 pendingDepositValue);

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
basketaddressBasket token address.
basketValueuint256Current value of the basket in USD.
baseAssetBalanceuint256Current balance of the base asset in the basket.
pendingDeposituint256Current assets pending deposit in the given basket.
baseAssetIndexuint256

Returns

NameTypeDescription
totalSupplyuint256Total supply of the basket token after processing pending deposits.
pendingDepositValueuint256Value of the pending deposits in USD.

_calculateTargetBalances

Internal function to calculate the target balances for each asset in a given basket.

function _calculateTargetBalances(
    BasketManagerStorage storage self,
    address basket,
    uint256 basketValue,
    uint256 requiredWithdrawValue,
    address[] memory assets,
    uint64[] memory proposedTargetWeights
)
    private
    view
    returns (uint256[] memory targetBalances);

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
basketaddressBasket token address.
basketValueuint256Current value of the basket in USD.
requiredWithdrawValueuint256Value of the assets to be withdrawn from the basket.
assetsaddress[]Array of asset addresses in the basket.
proposedTargetWeightsuint64[]

Returns

NameTypeDescription
targetBalancesuint256[]Array of target balances for each asset in the basket.

_calculateBasketValue

Internal function to calculate the current value of all assets in a given basket.

function _calculateBasketValue(
    BasketManagerStorage storage self,
    address basket,
    address[] memory assets
)
    private
    view
    returns (uint256[] memory balances, uint256 basketValue);

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
basketaddressBasket token address.
assetsaddress[]Array of asset addresses in the basket.

Returns

NameTypeDescription
balancesuint256[]Array of balances of each asset in the basket.
basketValueuint256Current value of the basket in USD.

_isRebalanceRequired

Internal function to check if a rebalance is required for the given basket.

A rebalance is required if the difference between the current asset balances and the target balances is greater than 0. We assume the permissioned caller has already validated the condition to call this function optimally.

function _isRebalanceRequired(
    address[] memory assets,
    uint256[] memory balances,
    uint256[] memory targetBalances
)
    private
    view
    returns (bool shouldRebalance);

Parameters

NameTypeDescription
assetsaddress[]Array of asset addresses in the basket.
balancesuint256[]Array of balances of each asset in the basket.
targetBalancesuint256[]Array of target balances for each asset in the basket.

Returns

NameTypeDescription
shouldRebalanceboolBoolean indicating if a rebalance is required.

_setBaseAssetIndex

Internal function to store the index of the base asset for a given basket. Reverts if the base asset is not present in the basket's assets.

If the base asset is not present in the basket, this function will revert.

function _setBaseAssetIndex(
    BasketManagerStorage storage self,
    address basket,
    address[] memory assets,
    address baseAsset
)
    private;

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
basketaddressBasket token address.
assetsaddress[]Array of asset addresses in the basket.
baseAssetaddressBase asset address.

_createRebalanceBitMask

Internal function to create a bitmask for baskets being rebalanced.

A bitmask like 00000011 indicates that the first two baskets are being rebalanced.

function _createRebalanceBitMask(
    BasketManagerStorage storage self,
    address[] memory baskets
)
    private
    view
    returns (uint256 basketMask);

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
basketsaddress[]Array of basket addresses currently being rebalanced.

Returns

NameTypeDescription
basketMaskuint256Bitmask for baskets being rebalanced.

Events

InternalTradeSettled

EVENTS ///

Emitted when an internal trade is settled.

event InternalTradeSettled(InternalTrade internalTrade, uint256 buyAmount);

Parameters

NameTypeDescription
internalTradeInternalTradeInternal trade that was settled.
buyAmountuint256Amount of the the from token that is traded.

SwapFeeCharged

Emitted when swap fees are charged on an internal trade.

event SwapFeeCharged(address indexed asset, uint256 amount);

Parameters

NameTypeDescription
assetaddressAsset that the swap fee was charged in.
amountuint256Amount of the asset that was charged.

RebalanceProposed

Emitted when a rebalance is proposed for a set of baskets

event RebalanceProposed(uint40 indexed epoch, address[] baskets, uint64[][] proposedTargetWeights, bytes32 basketHash);

Parameters

NameTypeDescription
epochuint40Unique identifier for the rebalance, incremented each time a rebalance is proposed
basketsaddress[]Array of basket addresses to rebalance
proposedTargetWeightsuint64[][]Array of target weights for each basket
basketHashbytes32Hash of the basket addresses and target weights for the rebalance

RebalanceCompleted

Emitted when a rebalance is completed.

event RebalanceCompleted(uint40 indexed epoch);

Errors

ZeroTotalSupply

ERRORS ///

Reverts when the total supply of a basket token is zero.

error ZeroTotalSupply();

ZeroBurnedShares

Reverts when the amount of burned shares is zero.

error ZeroBurnedShares();

CannotBurnMoreSharesThanTotalSupply

Reverts when trying to burn more shares than the total supply.

error CannotBurnMoreSharesThanTotalSupply();

BasketTokenNotFound

Reverts when the requested basket token is not found.

error BasketTokenNotFound();

AssetNotFoundInBasket

Reverts when the requested asset is not found in the basket.

error AssetNotFoundInBasket();

BasketTokenAlreadyExists

Reverts when trying to create a basket token that already exists.

error BasketTokenAlreadyExists();

BasketTokenMaxExceeded

Reverts when the maximum number of basket tokens has been reached.

error BasketTokenMaxExceeded();

ElementIndexNotFound

Reverts when the requested element index is not found.

error ElementIndexNotFound();

StrategyRegistryDoesNotSupportStrategy

Reverts when the strategy registry does not support the given strategy.

error StrategyRegistryDoesNotSupportStrategy();

BasketsMismatch

Reverts when the baskets or target weights do not match the proposed rebalance.

error BasketsMismatch();

BaseAssetMismatch

Reverts when the base asset does not match the given asset.

error BaseAssetMismatch();

AssetListEmpty

Reverts when the asset is not found in the asset registry.

error AssetListEmpty();

MustWaitForRebalanceToComplete

Reverts when a rebalance is in progress and the caller must wait for it to complete.

error MustWaitForRebalanceToComplete();

NoRebalanceInProgress

Reverts when there is no rebalance in progress.

error NoRebalanceInProgress();

TooEarlyToCompleteRebalance

Reverts when it is too early to complete the rebalance.

error TooEarlyToCompleteRebalance();

TooEarlyToProposeRebalance

Reverts when it is too early to propose a rebalance.

error TooEarlyToProposeRebalance();

RebalanceNotRequired

Reverts when a rebalance is not required.

error RebalanceNotRequired();

ExternalTradeSlippage

Reverts when the external trade slippage exceeds the allowed limit.

error ExternalTradeSlippage();

TargetWeightsNotMet

Reverts when the target weights are not met.

error TargetWeightsNotMet();

InternalTradeMinMaxAmountNotReached

Reverts when the minimum or maximum amount is not reached for an internal trade.

error InternalTradeMinMaxAmountNotReached();

IncorrectTradeTokenAmount

Reverts when the trade token amount is incorrect.

error IncorrectTradeTokenAmount();

ExternalTradeMismatch

Reverts when given external trades do not match.

error ExternalTradeMismatch();

CompleteTokenSwapFailed

Reverts when the delegatecall to the tokenswap adapter fails.

error CompleteTokenSwapFailed();

AssetNotEnabled

Reverts when an asset included in a bit flag is not enabled in the asset registry.

error AssetNotEnabled();

Structs

InternalTradeInfo

STRUCTS ///

Struct containing data for an internal trade.

struct InternalTradeInfo {
    uint256 fromBasketIndex;
    uint256 toBasketIndex;
    uint256 sellTokenAssetIndex;
    uint256 buyTokenAssetIndex;
    uint256 toBasketBuyTokenIndex;
    uint256 toBasketSellTokenIndex;
    uint256 netBuyAmount;
    uint256 netSellAmount;
    uint256 feeOnBuy;
    uint256 feeOnSell;
}

ExternalTradeInfo

Struct containing data for an external trade.

struct ExternalTradeInfo {
    uint256 sellTokenPrice;
    uint256 buyTokenPrice;
    uint256 sellValue;
    uint256 internalMinAmount;
    uint256 diff;
}

BasketOwnershipInfo

Struct containing data for basket ownership of an external trade.

struct BasketOwnershipInfo {
    uint256 basketIndex;
    uint256 buyTokenAssetIndex;
    uint256 sellTokenAssetIndex;
}

BitFlag

Git Source

State Variables

MASK_ODD_BITS

uint256 private constant MASK_ODD_BITS = 0x5555555555555555555555555555555555555555555555555555555555555555;

MASK_EVEN_PAIRS

uint256 private constant MASK_EVEN_PAIRS = 0x3333333333333333333333333333333333333333333333333333333333333333;

MASK_NIBBLES

uint256 private constant MASK_NIBBLES = 0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F;

BYTE_MULTIPLIER

uint256 private constant BYTE_MULTIPLIER = 0x0101010101010101010101010101010101010101010101010101010101010101;

Functions

popCount

Counts the number of set bits in a bit flag using parallel counting. This algorithm is based on the "Counting bits set, in parallel" technique from: https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel

function popCount(uint256 bitFlag) internal pure returns (uint256);

Parameters

NameTypeDescription
bitFlaguint256The bit flag to count the number of set bits.

Returns

NameTypeDescription
<none>uint256count The number of set bits in the bit flag.

Errors

Git Source

Library containing shared custom errors the protocol may revert with.

Errors

ZeroAddress

Thrown when an empty address is given as parameter to a function that does not allow it.

error ZeroAddress();

ZeroAmount

Thrown when an 0 is given as amount parameter to a function that does not allow it.

error ZeroAmount();

MathUtils

Git Source

A library to perform math operations with optimizations.

This library is based on the code snippet from the OpenZeppelin Contracts Math library. https://github.com/OpenZeppelin/openzeppelin-contracts/blob/05d4bf57ffed8c65256ff4ede5c3cf7a0b738e7d/contracts/utils/math/Math.sol

Functions

diff

Calculates the absolute difference between two unsigned integers.

function diff(uint256 a, uint256 b) internal pure returns (uint256);

Parameters

NameTypeDescription
auint256The first number.
buint256The second number.

Returns

NameTypeDescription
<none>uint256The absolute difference between a and b.

Contents

AutomaticWeightStrategy

Git Source

Inherits: WeightStrategy, AccessControlEnumerable

A strategy that returns the target weights based on external market cap data. This could be used for other purposes as well such as volume, liquidity, etc as long as the data is available on chain. Setters should not be implemented in this contract as the data is expected to be external and read-only.

Functions

constructor

constructor(address admin) payable;

getTargetWeights

function getTargetWeights(uint256 bitFlag) public view virtual override returns (uint64[] memory targetWeights);

supportsBitFlag

function supportsBitFlag(uint256 bitFlag) public view virtual override returns (bool);

ManagedWeightStrategy

Git Source

Inherits: WeightStrategy, AccessControlEnumerable

A custom weight strategy that allows manual setting of target weights for a basket.

Inherits from WeightStrategy and AccessControlEnumerable for role-based access control.

State Variables

targetWeights

Maps each rebalance bit flag to the corresponding target weights.

mapping(uint256 bitFlag => uint64[] weights) public targetWeights;

lastUpdated

Maps each bit flag to the last updated epoch and timestamp.

mapping(uint256 bitFlag => LastUpdated) public lastUpdated;

_MANAGER_ROLE

Role identifier for the manager role.

bytes32 internal constant _MANAGER_ROLE = keccak256("MANAGER_ROLE");

_WEIGHT_PRECISION

Precision for weights. All results from getTargetWeights() should sum to _WEIGHT_PRECISION.

uint64 internal constant _WEIGHT_PRECISION = 1e18;

_basketManager

Address of the BasketManager contract associated with this strategy.

address internal immutable _basketManager;

Functions

constructor

Constructor for the ManagedWeightStrategy contract.

constructor(address admin, address basketManager) payable;

Parameters

NameTypeDescription
adminaddressThe address of the admin who will have DEFAULT_ADMIN_ROLE and MANAGER_ROLE.
basketManageraddressThe address of the BasketManager contract associated with this strategy.

setTargetWeights

Sets the target weights for the assets for the next epoch. If a rebalance is in progress, the weights will apply to the next epoch.

Only callable by accounts with the MANAGER_ROLE.

function setTargetWeights(uint256 bitFlag, uint64[] calldata newTargetWeights) external onlyRole(_MANAGER_ROLE);

Parameters

NameTypeDescription
bitFlaguint256The bit flag representing the assets.
newTargetWeightsuint64[]The array of target weights for each asset.

getTargetWeights

Retrieves the target weights for the assets in the basket for a given epoch and bit flag.

function getTargetWeights(uint256 bitFlag) public view override returns (uint64[] memory weights);

Parameters

NameTypeDescription
bitFlaguint256The bit flag representing the assets.

Returns

NameTypeDescription
weightsuint64[]The target weights for the assets.

supportsBitFlag

Checks if the strategy supports the given bit flag, representing a list of assets.

function supportsBitFlag(uint256 bitFlag) public view virtual override returns (bool);

Parameters

NameTypeDescription
bitFlaguint256The bit flag representing the assets.

Returns

NameTypeDescription
<none>boolA boolean indicating whether the strategy supports the given bit flag.

Events

TargetWeightsUpdated

Emitted when target weights are updated.

event TargetWeightsUpdated(uint256 indexed bitFlag, uint256 indexed epoch, uint256 timestamp, uint64[] newWeights);

Parameters

NameTypeDescription
bitFlaguint256The bit flag representing the assets.
epochuint256The epoch for which the weights are updated for.
timestampuint256The timestamp of the update.
newWeightsuint64[]The new target weights.

Errors

UnsupportedBitFlag

Error thrown when an unsupported bit flag is provided.

error UnsupportedBitFlag();

InvalidWeightsLength

Error thrown when the length of the weights array does not match the number of assets.

error InvalidWeightsLength();

WeightsSumMismatch

Error thrown when the sum of the weights does not equal _WEIGHT_PRECISION (100%).

error WeightsSumMismatch();

NoTargetWeights

Error thrown when no target weights are set for the given epoch and bit flag.

error NoTargetWeights();

Structs

LastUpdated

Struct to store the last updated epoch and timestamp for a bit flag.

struct LastUpdated {
    uint40 epoch;
    uint40 timestamp;
}

StrategyRegistry

Git Source

Inherits: AccessControlEnumerable

A registry for weight strategies that allows checking if a strategy supports a specific bit flag.

*Inherits from AccessControlEnumerable for role-based access control. Roles:

  • DEFAULT_ADMIN_ROLE: The default role given to an address at creation. Can grant and revoke roles.
  • WEIGHT_STRATEGY_ROLE: Role given to approved weight strategys.*

State Variables

_WEIGHT_STRATEGY_ROLE

Role identifier for weight strategys

bytes32 private constant _WEIGHT_STRATEGY_ROLE = keccak256("WEIGHT_STRATEGY_ROLE");

Functions

constructor

Constructs the StrategyRegistry contract

constructor(address admin) payable;

Parameters

NameTypeDescription
adminaddressThe address that will be granted the DEFAULT_ADMIN_ROLE

supportsBitFlag

Checks if a given weight strategy supports a specific bit flag

function supportsBitFlag(uint256 bitFlag, address weightStrategy) external view returns (bool);

Parameters

NameTypeDescription
bitFlaguint256The bit flag to check support for
weightStrategyaddressThe address of the weight strategy to check

Returns

NameTypeDescription
<none>boolbool True if the strategy supports the bit flag, false otherwise

Errors

StrategyNotSupported

Error thrown when an unsupported strategy is used

error StrategyNotSupported();

WeightStrategy

Git Source

Abstract contract for weight strategies that determine the target weights of assets in a basket.

*This contract should be implemented by strategies that provide specific logic for calculating target weights. Use cases include:

  • AutomaticWeightStrategy.sol: Calculates weights based on external market data or other on-chain data sources.
  • ManagedWeightStrategy.sol: Allows manual setting of target weights by an authorized manager. The sum of the weights returned by getTargetWeights should be 1e18.*

Functions

getTargetWeights

Returns the target weights for the assets in the basket that the rebalancing process aims to achieve.

function getTargetWeights(uint256 bitFlag) public view virtual returns (uint64[] memory targetWeights);

Parameters

NameTypeDescription
bitFlaguint256The bit flag representing a list of assets.

Returns

NameTypeDescription
targetWeightsuint64[]The target weights of the assets in the basket. The weights should sum to 1e18.

supportsBitFlag

Checks whether the strategy supports the given bit flag, representing a list of assets.

function supportsBitFlag(uint256 bitFlag) public view virtual returns (bool supported);

Parameters

NameTypeDescription
bitFlaguint256The bit flag representing a list of assets.

Returns

NameTypeDescription
supportedboolA boolean indicating whether the strategy supports the given bit flag.

Contents

CoWSwapAdapter

Git Source

Inherits: TokenSwapAdapter

Adapter for executing and completing token swaps using CoWSwap protocol.

State Variables

_COWSWAP_ADAPTER_STORAGE

CONSTANTS ///

Storage slot for CoWSwapAdapter specific data.

bytes32 internal constant _COWSWAP_ADAPTER_STORAGE =
    bytes32(uint256(keccak256("cove.basketmanager.cowswapadapter.storage")) - 1);

cloneImplementation

Address of the clone implementation used for creating CoWSwapClone contracts.

address public immutable cloneImplementation;

Functions

constructor

Constructor to initialize the CoWSwapAdapter with the clone implementation address.

constructor(address cloneImplementation_) payable;

Parameters

NameTypeDescription
cloneImplementation_addressThe address of the clone implementation contract.

executeTokenSwap

Executes a series of token swaps by creating orders on the CoWSwap protocol.

function executeTokenSwap(ExternalTrade[] calldata externalTrades, bytes calldata) external payable override;

Parameters

NameTypeDescription
externalTradesExternalTrade[]The external trades to execute.
<none>bytes

completeTokenSwap

Completes the token swaps by claiming the tokens from the CoWSwapClone contracts.

function completeTokenSwap(ExternalTrade[] calldata externalTrades)
    external
    payable
    override
    returns (uint256[2][] memory claimedAmounts);

Parameters

NameTypeDescription
externalTradesExternalTrade[]The external trades that were executed and need to be settled.

Returns

NameTypeDescription
claimedAmountsuint256[2][]A 2D array containing the claimed amounts of sell and buy tokens for each trade.

_createOrder

Internal function to create an order on the CoWSwap protocol.

function _createOrder(
    address sellToken,
    address buyToken,
    uint256 sellAmount,
    uint256 buyAmount,
    uint32 validTo
)
    internal;

Parameters

NameTypeDescription
sellTokenaddressThe address of the token to sell.
buyTokenaddressThe address of the token to buy.
sellAmountuint256The amount of the sell token.
buyAmountuint256The minimum amount of the buy token.
validTouint32The timestamp until which the order is valid.

_cowswapAdapterStorage

Internal function to retrieve the storage for the CoWSwapAdapter.

function _cowswapAdapterStorage() internal pure returns (CoWSwapAdapterStorage storage s);

Returns

NameTypeDescription
sCoWSwapAdapterStorageThe storage struct for the CoWSwapAdapter.

Events

OrderCreated

EVENTS ///

Emitted when a new order is created.

event OrderCreated(
    address indexed sellToken,
    address indexed buyToken,
    uint256 sellAmount,
    uint256 buyAmount,
    uint32 validTo,
    address swapContract
);

Parameters

NameTypeDescription
sellTokenaddressThe address of the token to be sold.
buyTokenaddressThe address of the token to be bought.
sellAmountuint256The amount of the sell token.
buyAmountuint256The amount of the buy token.
validTouint32The timestamp until which the order is valid.
swapContractaddressThe address of the swap contract.

TokenSwapCompleted

Emitted when a token swap is completed.

event TokenSwapCompleted(
    address indexed sellToken,
    address indexed buyToken,
    uint256 claimedSellAmount,
    uint256 claimedBuyAmount,
    address swapContract
);

Parameters

NameTypeDescription
sellTokenaddressThe address of the token sold.
buyTokenaddressThe address of the token bought.
claimedSellAmountuint256The amount of sell tokens claimed.
claimedBuyAmountuint256The amount of buy tokens claimed.
swapContractaddressThe address of the swap contract.

Structs

CoWSwapAdapterStorage

STRUCTS ///

Structure to store adapter-specific data.

struct CoWSwapAdapterStorage {
    uint32 orderValidTo;
}

CoWSwapClone

Git Source

Inherits: IERC1271, Clone

A contract that implements the ERC1271 interface for signature validation and manages token trades. This contract is designed to be used as a clone with immutable arguments, leveraging the ClonesWithImmutableArgs library. The clone should be initialized with the following packed bytes, in this exact order:

  • sellToken (address): The address of the token to be sold.
  • buyToken (address): The address of the token to be bought.
  • sellAmount (uint256): The amount of the sell token.
  • buyAmount (uint256): The minimum amount of the buy token.
  • validTo (uint64): The timestamp until which the order is valid.
  • operator (address): The address of the operator allowed to manage the trade.
  • receiver (address): The address that will receive the bought tokens. To use this contract, deploy it as a clone using the ClonesWithImmutableArgs library with the above immutable arguments packed into a single bytes array. After deployment, call initialize() to set up the necessary token approvals for the trade.

The isValidSignature function can be used to validate the signature of an order against the stored order digest.

State Variables

_ERC1271_MAGIC_VALUE

CONSTANTS ///

bytes4 internal constant _ERC1271_MAGIC_VALUE = 0x1626ba7e;

_ERC1271_NON_MAGIC_VALUE

bytes4 internal constant _ERC1271_NON_MAGIC_VALUE = 0xffffffff;

_COW_SETTLEMENT_DOMAIN_SEPARATOR

The domain separator of GPv2Settlement contract used for orderDigest calculation.

bytes32 internal constant _COW_SETTLEMENT_DOMAIN_SEPARATOR =
    0xc078f884a2676e1345748b1feace7b0abee5d00ecadb6e574dcdd109a63e8943;

_VAULT_RELAYER

Address of the GPv2VaultRelayer. https://docs.cow.fi/cow-protocol/reference/contracts/core

address internal constant _VAULT_RELAYER = 0xC92E8bdf79f0507f65a392b0ab4667716BFE0110;

Functions

initialize

Initializes the CoWSwapClone contract by approving the vault relayer to spend the maximum amount of the sell token.

This function should be called after the clone is deployed to set up the necessary token approvals.

function initialize() external payable;

isValidSignature

Validates the signature of an order. The order is considered valid if the order digest matches the stored order digest. Second parameter is not used.

function isValidSignature(bytes32 orderDigest, bytes calldata encodedOrder) external view override returns (bytes4);

Parameters

NameTypeDescription
orderDigestbytes32The digest of the order to validate.
encodedOrderbytes

Returns

NameTypeDescription
<none>bytes4A magic value if the signature is valid, otherwise a non-magic value.

claim

Claims the sell and buy tokens. Calling this function before the trade has settled will cancel the trade. Only the operator or the receiver can claim the tokens.

function claim() external payable returns (uint256 claimedSellAmount, uint256 claimedBuyAmount);

Returns

NameTypeDescription
claimedSellAmountuint256The amount of sell tokens claimed.
claimedBuyAmountuint256The amount of buy tokens claimed.

sellToken

Returns the address of the sell token.

function sellToken() public pure returns (address);

Returns

NameTypeDescription
<none>addressThe address of the sell token.

buyToken

Returns the address of the buy token.

function buyToken() public pure returns (address);

Returns

NameTypeDescription
<none>addressThe address of the buy token.

sellAmount

Returns the amount of sell tokens.

function sellAmount() public pure returns (uint256);

Returns

NameTypeDescription
<none>uint256The amount of sell tokens.

minBuyAmount

Returns the amount of buy tokens.

function minBuyAmount() public pure returns (uint256);

Returns

NameTypeDescription
<none>uint256The amount of buy tokens.

validTo

Returns the timestamp until which the order is valid.

function validTo() public pure returns (uint32);

Returns

NameTypeDescription
<none>uint32The timestamp until which the order is valid.

receiver

Returns the address of the receiver.

function receiver() public pure returns (address);

Returns

NameTypeDescription
<none>addressThe address of the receiver.

operator

Returns the address of the operator who can claim the tokens after the trade has settled. The operator can also cancel the trade before it has settled by calling the claim function before the trade has settled.

function operator() public pure returns (address);

Returns

NameTypeDescription
<none>addressThe address of the operator.

Events

OrderCreated

EVENTS ///

Emitted when a new order is created.

event OrderCreated(
    address indexed sellToken,
    address indexed buyToken,
    uint256 sellAmount,
    uint256 minBuyAmount,
    uint32 validTo,
    address indexed receiver,
    address operator
);

Parameters

NameTypeDescription
sellTokenaddressThe address of the token to be sold.
buyTokenaddressThe address of the token to be bought.
sellAmountuint256The amount of the sell token.
minBuyAmountuint256The minimum amount of the buy token.
validTouint32The timestamp until which the order is valid.
receiveraddressThe address that will receive the bought tokens.
operatoraddressThe address of the operator allowed to manage the trade.

OrderClaimed

Emitted when an order is claimed.

event OrderClaimed(address indexed operator, uint256 claimedSellAmount, uint256 claimedBuyAmount);

Parameters

NameTypeDescription
operatoraddressThe address of the operator who claimed the order.
claimedSellAmountuint256The amount of sell tokens claimed.
claimedBuyAmountuint256The amount of buy tokens claimed.

Errors

CallerIsNotOperatorOrReceiver

ERRORS ///

Thrown when the caller is not the operator or receiver of the order.

error CallerIsNotOperatorOrReceiver();

TokenSwapAdapter

Git Source

Abstract contract for token swap adapters

Functions

executeTokenSwap

Executes series of token swaps and returns the hashes of the orders submitted/executed

function executeTokenSwap(ExternalTrade[] calldata externalTrades, bytes calldata data) external payable virtual;

Parameters

NameTypeDescription
externalTradesExternalTrade[]The external trades to execute
databytes

completeTokenSwap

Completes the token swaps by confirming each order settlement and claiming the resulting tokens (if necessary).

*This function must return the exact amounts of sell tokens and buy tokens claimed per trade. If the adapter operates asynchronously (e.g., CoWSwap), this function should handle the following:

  • Cancel any unsettled trades to prevent further execution.
  • Claim the remaining tokens from the unsettled trades.*
function completeTokenSwap(ExternalTrade[] calldata externalTrades)
    external
    payable
    virtual
    returns (uint256[2][] memory claimedAmounts);

Parameters

NameTypeDescription
externalTradesExternalTrade[]The external trades that were executed and need to be settled.

Returns

NameTypeDescription
claimedAmountsuint256[2][]A 2D array where each element contains the claimed amounts of sell tokens and buy tokens for each corresponding trade in externalTrades. The first element of each sub-array is the claimed sell amount, and the second element is the claimed buy amount.

Contents

Status

Git Source

Enum representing the status of a rebalance.

enum Status {
    NOT_STARTED,
    REBALANCE_PROPOSED,
    TOKEN_SWAP_PROPOSED,
    TOKEN_SWAP_EXECUTED
}

RebalanceStatus

Git Source

Struct representing the rebalance status.

struct RebalanceStatus {
    bytes32 basketHash;
    uint256 basketMask;
    uint40 epoch;
    uint40 timestamp;
    Status status;
}

BasketManagerStorage

Git Source

Struct representing the storage of the BasketManager contract.

struct BasketManagerStorage {
    StrategyRegistry strategyRegistry;
    EulerRouter eulerRouter;
    address assetRegistry;
    address feeCollector;
    mapping(address => uint16) managementFees;
    uint16 swapFee;
    address basketTokenImplementation;
    address[] basketTokens;
    mapping(address basketToken => mapping(address asset => uint256 balance)) basketBalanceOf;
    mapping(bytes32 basketId => address basketToken) basketIdToAddress;
    mapping(address basketToken => address[] basketAssets) basketAssets;
    mapping(address basketToken => mapping(address basketAsset => uint256 indexPlusOne)) basketAssetToIndexPlusOne;
    mapping(address basketToken => uint256 indexPlusOne) basketTokenToIndexPlusOne;
    mapping(address basketToken => uint256 pendingRedeems) pendingRedeems;
    mapping(address asset => uint256 fees) collectedSwapFees;
    mapping(address basket => uint256 indexPlusOne) basketTokenToBaseAssetIndexPlusOne;
    RebalanceStatus rebalanceStatus;
    bytes32 externalTradesHash;
    uint8 retryCount;
    address tokenSwapAdapter;
}

InternalTrade

Git Source

Struct containing data for an internal trade.

struct InternalTrade {
    address fromBasket;
    address sellToken;
    address buyToken;
    address toBasket;
    uint256 sellAmount;
    uint256 minAmount;
    uint256 maxAmount;
}

ExternalTrade

Git Source

Struct containing data for an external trade.

struct ExternalTrade {
    address sellToken;
    address buyToken;
    uint256 sellAmount;
    uint256 minAmount;
    BasketTradeOwnership[] basketTradeOwnership;
}

BasketTradeOwnership

Git Source

Struct representing a baskets ownership of an external trade.

struct BasketTradeOwnership {
    address basket;
    uint96 tradeOwnership;
}

AnchoredOracle

Git Source

Inherits: BaseAdapter

Author: Storm Labs (https://storm-labs.xyz/)

PriceOracle that chains two PriceOracles.

Euler's experimental implementation was used as a reference: https://github.com/euler-xyz/euler-price-oracle/blob/experiments/src/aggregator/AnchoredOracle.sol

State Variables

_MAX_DIVERGENCE_LOWER_BOUND

The lower bound for maxDivergence, 0.1%.

uint256 internal constant _MAX_DIVERGENCE_LOWER_BOUND = 0.001e18;

_MAX_DIVERGENCE_UPPER_BOUND

The upper bound for maxDivergence, 50%.

uint256 internal constant _MAX_DIVERGENCE_UPPER_BOUND = 0.5e18;

_WAD

The denominator for maxDivergence.

uint256 internal constant _WAD = 1e18;

name

The name of the oracle.

string public constant name = "AnchoredOracle";

primaryOracle

The address of the primary oracle.

address public immutable primaryOracle;

anchorOracle

The address of the anchor oracle.

address public immutable anchorOracle;

maxDivergence

The maximum divergence allowed, denominated in _WAD.

uint256 public immutable maxDivergence;

Functions

constructor

Deploys an AnchoredOracle contract.

constructor(address _primaryOracle, address _anchorOracle, uint256 _maxDivergence) payable;

Parameters

NameTypeDescription
_primaryOracleaddressThe address of the primary oracle used for obtaining price quotes.
_anchorOracleaddressThe address of the anchor oracle used for validating price quotes.
_maxDivergenceuint256The maximum allowed divergence between the primary and anchor oracle prices, denominated in _WAD.

_getQuote

Retrieves a price quote from the primaryOracle and ensures that anchorOracle price does not diverge by more than +/- the percent threshold. For example with a 50% threshold, a primary quote of 10 would check that the anchor is between 5 and 15.

function _getQuote(uint256 inAmount, address base, address quote) internal view override returns (uint256);

Parameters

NameTypeDescription
inAmountuint256The amount of base token to be converted.
baseaddressThe token for which the price is being determined.
quoteaddressThe token against which the price is measured.

Returns

NameTypeDescription
<none>uint256The price quote from the primaryOracle.

AssetRegistry

Git Source

Inherits: AccessControlEnumerable

This contract provides functionality to add, enable, pause, and manage assets, with role-based access control.

Manages the registration and status of assets in the system.

Utilizes OpenZeppelin's AccessControlEnumerable for granular permission management.

Supports three asset states: DISABLED -> ENABLED <-> PAUSED.

State Variables

_MANAGER_ROLE

CONSTANTS ///

Role responsible for managing assets in the registry.

bytes32 private constant _MANAGER_ROLE = keccak256("MANAGER_ROLE");

_MAX_ASSETS

Maximum number of assets that can be registered in the system.

uint256 private constant _MAX_ASSETS = 255;

_assetList

STATE VARIABLES ///

Array of assets registered in the system.

address[] private _assetList;

_assetRegistry

Mapping from asset address to AssetData struct containing the asset's index and status.

mapping(address asset => AssetData) private _assetRegistry;

enabledAssets

Bit flag representing the enabled assets in the registry.

uint256 public enabledAssets;

Functions

constructor

Initializes the AssetRegistry contract

Sets up initial roles for admin and manager

*Reverts if:

  • The admin address is zero (Errors.ZeroAddress)*
constructor(address admin) payable;

Parameters

NameTypeDescription
adminaddressThe address to be granted the DEFAULT_ADMIN_ROLE

addAsset

Adds a new asset to the registry

Only callable by accounts with the MANAGER_ROLE

*Reverts if:

  • The caller doesn't have the MANAGER_ROLE (OpenZeppelin's AccessControl)
  • The asset address is zero (Errors.ZeroAddress)
  • The asset is already enabled (AssetAlreadyEnabled)
  • The maximum number of assets has been reached (MaxAssetsReached)*
function addAsset(address asset) external onlyRole(_MANAGER_ROLE);

Parameters

NameTypeDescription
assetaddressThe address of the asset to be added

setAssetStatus

Sets the status of an asset in the registry

Only callable by accounts with the MANAGER_ROLE

*Reverts if:

  • The caller doesn't have the MANAGER_ROLE (OpenZeppelin's AccessControl)
  • The asset address is zero (Errors.ZeroAddress)
  • The asset is not enabled in the registry (AssetNotEnabled)
  • The new status is invalid (AssetInvalidStatusUpdate)*
function setAssetStatus(address asset, AssetStatus newStatus) external onlyRole(_MANAGER_ROLE);

Parameters

NameTypeDescription
assetaddressThe address of the asset to update
newStatusAssetStatusThe new status to set (ENABLED or PAUSED)

getAssetStatus

Retrieves the status of an asset

Returns the status of the asset. For non-existent assets, returns status as DISABLED

function getAssetStatus(address asset) external view returns (AssetStatus);

Parameters

NameTypeDescription
assetaddressThe address of the asset to query

Returns

NameTypeDescription
<none>AssetStatusAssetStatus The status of the asset

getAssets

Retrieves the list of assets in the registry. Parameter bitFlag is used to filter the assets.

function getAssets(uint256 bitFlag) external view returns (address[] memory assets);

Parameters

NameTypeDescription
bitFlaguint256The bit flag to filter the assets.

Returns

NameTypeDescription
assetsaddress[]The list of assets in the registry.

getAllAssets

Retrieves the addresses of all assets in the registry without any filtering.

function getAllAssets() external view returns (address[] memory);

Returns

NameTypeDescription
<none>address[]assets The list of addresses of all assets in the registry.

hasPausedAssets

Checks if any assets in the given bit flag are paused.

function hasPausedAssets(uint256 bitFlag) external view returns (bool);

Parameters

NameTypeDescription
bitFlaguint256The bit flag representing a set of assets.

Returns

NameTypeDescription
<none>boolbool True if any of the assets are paused, false otherwise.

getAssetsBitFlag

Retrieves the bit flag for a given list of assets.

*This function is for off-chain usage to get the bit flag for a list of assets. Reverts if:

  • the number of assets exceeds the maximum number of assets
  • an asset is not enabled in the registry*
function getAssetsBitFlag(address[] memory assets) external view returns (uint256);

Parameters

NameTypeDescription
assetsaddress[]The list of assets to get the bit flag for.

Returns

NameTypeDescription
<none>uint256bitFlag The bit flag representing the list of assets.

Events

AddAsset

EVENTS ///

Emitted when a new asset is added to the registry.

event AddAsset(address indexed asset);

SetAssetStatus

Emitted when an asset's status is updated.

event SetAssetStatus(address indexed asset, AssetStatus status);

Errors

AssetAlreadyEnabled

ERRORS ///

Thrown when attempting to add an asset that is already enabled in the registry.

error AssetAlreadyEnabled();

AssetNotEnabled

Thrown when attempting to perform an operation on an asset that is not enabled in the registry.

error AssetNotEnabled();

AssetInvalidStatusUpdate

Thrown when attempting to set the asset status to an invalid status.

error AssetInvalidStatusUpdate();

MaxAssetsReached

Thrown when attempting to add an asset when the maximum number of assets has been reached.

error MaxAssetsReached();

AssetExceedsMaximum

Thrown when length of the requested assets exceeds the maximum number of assets.

error AssetExceedsMaximum();

Structs

AssetData

STRUCTS ///

Contains the index and status of an asset in the registry.

struct AssetData {
    uint32 indexPlusOne;
    AssetStatus status;
}

Enums

AssetStatus

ENUMS ///

enum AssetStatus {
    DISABLED,
    ENABLED,
    PAUSED
}

BasketManager

Git Source

Inherits: ReentrancyGuardTransient, AccessControlEnumerable, Pausable

Contract responsible for managing baskets and their tokens. The accounting for assets per basket is done in the BasketManagerUtils contract.

State Variables

_MANAGER_ROLE

LIBRARIES /// CONSTANTS ///

Manager role. Managers can create new baskets.

bytes32 private constant _MANAGER_ROLE = keccak256("MANAGER_ROLE");

_PAUSER_ROLE

Pauser role.

bytes32 private constant _PAUSER_ROLE = keccak256("PAUSER_ROLE");

_REBALANCE_PROPOSER_ROLE

Rebalance Proposer role. Rebalance proposers can propose a new rebalance.

bytes32 private constant _REBALANCE_PROPOSER_ROLE = keccak256("REBALANCE_PROPOSER_ROLE");

_TOKENSWAP_PROPOSER_ROLE

TokenSwap Proposer role. Token swap proposers can propose a new token swap.

bytes32 private constant _TOKENSWAP_PROPOSER_ROLE = keccak256("TOKENSWAP_PROPOSER_ROLE");

_TOKENSWAP_EXECUTOR_ROLE

TokenSwap Executor role. Token swap executors can execute a token swap.

bytes32 private constant _TOKENSWAP_EXECUTOR_ROLE = keccak256("TOKENSWAP_EXECUTOR_ROLE");

_BASKET_TOKEN_ROLE

Basket token role. Given to the basket token contracts when they are created.

bytes32 private constant _BASKET_TOKEN_ROLE = keccak256("BASKET_TOKEN_ROLE");

_TIMELOCK_ROLE

Role given to a timelock contract that can set critical parameters.

bytes32 private constant _TIMELOCK_ROLE = keccak256("TIMELOCK_ROLE");

_MAX_MANAGEMENT_FEE

Maximum management fee (30%) in BPS denominated in 1e4.

uint16 private constant _MAX_MANAGEMENT_FEE = 3000;

_MAX_SWAP_FEE

Maximum swap fee (5%) in BPS denominated in 1e4.

uint16 private constant _MAX_SWAP_FEE = 500;

_bmStorage

STATE VARIABLES ///

Struct containing the BasketManagerUtils contract and other necessary data.

BasketManagerStorage private _bmStorage;

isOrderValid

Mapping of order hashes to their validity status.

mapping(bytes32 => bool) public isOrderValid;

Functions

constructor

Initializes the contract with the given parameters.

constructor(
    address basketTokenImplementation,
    address eulerRouter_,
    address strategyRegistry_,
    address assetRegistry_,
    address admin,
    address feeCollector_
)
    payable;

Parameters

NameTypeDescription
basketTokenImplementationaddressAddress of the basket token implementation.
eulerRouter_addressAddress of the oracle registry.
strategyRegistry_addressAddress of the strategy registry.
assetRegistry_addressAddress of the asset registry.
adminaddressAddress of the admin.
feeCollector_addressAddress of the fee collector.

basketTokenToIndex

PUBLIC FUNCTIONS ///

Returns the index of the basket token in the basketTokens array.

Reverts if the basket token does not exist.

function basketTokenToIndex(address basketToken) public view returns (uint256 index);

Parameters

NameTypeDescription
basketTokenaddressAddress of the basket token.

Returns

NameTypeDescription
indexuint256Index of the basket token.

basketTokenToRebalanceAssetToIndex

Returns the index of the basket asset in the basketAssets array.

Reverts if the basket asset does not exist.

function basketTokenToRebalanceAssetToIndex(address basketToken, address asset) public view returns (uint256 index);

Parameters

NameTypeDescription
basketTokenaddressAddress of the basket token.
assetaddressAddress of the asset.

Returns

NameTypeDescription
indexuint256Index of the basket asset.

numOfBasketTokens

Returns the number of basket tokens.

function numOfBasketTokens() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256Number of basket tokens.

basketTokens

Returns all basket token addresses.

function basketTokens() external view returns (address[] memory);

Returns

NameTypeDescription
<none>address[]Array of basket token addresses.

basketIdToAddress

Returns the basket token address with the given basketId.

The basketId is the keccak256 hash of the bitFlag and strategy address.

function basketIdToAddress(bytes32 basketId) external view returns (address);

Parameters

NameTypeDescription
basketIdbytes32Basket ID.

basketBalanceOf

Returns the balance of the given asset in the given basket.

function basketBalanceOf(address basketToken, address asset) external view returns (uint256);

Parameters

NameTypeDescription
basketTokenaddressAddress of the basket token.
assetaddressAddress of the asset.

Returns

NameTypeDescription
<none>uint256Balance of the asset in the basket.

rebalanceStatus

Returns the current rebalance status.

function rebalanceStatus() external view returns (RebalanceStatus memory);

Returns

NameTypeDescription
<none>RebalanceStatusRebalance status struct with the following fields: - basketHash: Hash of the baskets proposed for rebalance. - timestamp: Timestamp of the last action. - status: Status enum of the rebalance.

externalTradesHash

Returns the hash of the external trades stored during proposeTokenSwap

function externalTradesHash() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32Hash of the external trades

eulerRouter

Returns the address of the basket token implementation.

function eulerRouter() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the basket token implementation.

feeCollector

Returns the address of the feeCollector contract.

function feeCollector() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the feeCollector.

managementFee

Returns the management fee of a basket in BPS denominated in 1e4.

function managementFee(address basket) external view returns (uint16);

Parameters

NameTypeDescription
basketaddressAddress of the basket.

Returns

NameTypeDescription
<none>uint16Management fee.

swapFee

Returns the swap fee in BPS denominated in 1e4.

function swapFee() external view returns (uint16);

Returns

NameTypeDescription
<none>uint16Swap fee.

strategyRegistry

Returns the address of the strategy registry.

function strategyRegistry() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the strategy registry.

tokenSwapAdapter

Returns the address of the token swap adapter.

function tokenSwapAdapter() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the token swap adapter.

retryCount

Returns the retry count for the current rebalance epoch.

function retryCount() external view returns (uint8);

Returns

NameTypeDescription
<none>uint8Retry count.

basketAssets

Returns the addresses of all assets in the given basket.

function basketAssets(address basket) external view returns (address[] memory);

Parameters

NameTypeDescription
basketaddressAddress of the basket.

Returns

NameTypeDescription
<none>address[]Array of asset addresses.

createNewBasket

Creates a new basket token with the given parameters.

function createNewBasket(
    string calldata basketName,
    string calldata symbol,
    address baseAsset,
    uint256 bitFlag,
    address strategy
)
    external
    payable
    whenNotPaused
    onlyRole(_MANAGER_ROLE)
    returns (address basket);

Parameters

NameTypeDescription
basketNamestringName of the basket.
symbolstringSymbol of the basket.
baseAssetaddress
bitFlaguint256Asset selection bitFlag for the basket.
strategyaddressAddress of the strategy contract for the basket.

proposeRebalance

Proposes a rebalance for the given baskets. The rebalance is proposed if the difference between the target balance and the current balance of any asset in the basket is more than 500 USD.

function proposeRebalance(address[] calldata basketsToRebalance)
    external
    onlyRole(_REBALANCE_PROPOSER_ROLE)
    nonReentrant
    whenNotPaused;

Parameters

NameTypeDescription
basketsToRebalanceaddress[]Array of basket addresses to rebalance.

proposeTokenSwap

Proposes a set of internal trades and external trades to rebalance the given baskets. If the proposed token swap results are not close to the target balances, this function will revert.

This function can only be called after proposeRebalance.

function proposeTokenSwap(
    InternalTrade[] calldata internalTrades,
    ExternalTrade[] calldata externalTrades,
    address[] calldata basketsToRebalance,
    uint64[][] calldata targetWeights
)
    external
    onlyRole(_TOKENSWAP_PROPOSER_ROLE)
    nonReentrant
    whenNotPaused;

Parameters

NameTypeDescription
internalTradesInternalTrade[]Array of internal trades to execute.
externalTradesExternalTrade[]Array of external trades to execute.
basketsToRebalanceaddress[]Array of basket addresses currently being rebalanced.
targetWeightsuint64[][]Array of target weights for the baskets.

executeTokenSwap

Executes the token swaps proposed in proposeTokenSwap and updates the basket balances.

This function can only be called after proposeTokenSwap.

function executeTokenSwap(
    ExternalTrade[] calldata externalTrades,
    bytes calldata data
)
    external
    onlyRole(_TOKENSWAP_EXECUTOR_ROLE)
    nonReentrant
    whenNotPaused;

Parameters

NameTypeDescription
externalTradesExternalTrade[]Array of external trades to execute.
databytesEncoded data for the token swap.

setTokenSwapAdapter

Sets the address of the TokenSwapAdapter contract used to execute token swaps.

Only callable by the timelock.

function setTokenSwapAdapter(address tokenSwapAdapter_) external onlyRole(_TIMELOCK_ROLE);

Parameters

NameTypeDescription
tokenSwapAdapter_addressAddress of the TokenSwapAdapter contract.

completeRebalance

Completes the rebalance for the given baskets. The rebalance can be completed if it has been more than 15 minutes since the last action.

function completeRebalance(
    ExternalTrade[] calldata externalTrades,
    address[] calldata basketsToRebalance,
    uint64[][] calldata targetWeights
)
    external
    nonReentrant
    whenNotPaused;

Parameters

NameTypeDescription
externalTradesExternalTrade[]
basketsToRebalanceaddress[]Array of basket addresses proposed for rebalance.
targetWeightsuint64[][]Array of target weights for the baskets.

proRataRedeem

FALLBACK REDEEM LOGIC ///

Fallback redeem function to redeem shares when the rebalance is not in progress. Redeems the shares for each underlying asset in the basket pro-rata to the amount of shares redeemed.

function proRataRedeem(
    uint256 totalSupplyBefore,
    uint256 burnedShares,
    address to
)
    public
    nonReentrant
    whenNotPaused
    onlyRole(_BASKET_TOKEN_ROLE);

Parameters

NameTypeDescription
totalSupplyBeforeuint256Total supply of the basket token before the shares were burned.
burnedSharesuint256Amount of shares burned.
toaddressAddress to send the redeemed assets to.

setManagementFee

FEE FUNCTIONS ///

Set the management fee to be given to the treausry on rebalance.

Only callable by the timelock.

Setting the management fee of the 0 address will set the default management fee for newly created baskets.

function setManagementFee(address basket, uint16 managementFee_) external onlyRole(_TIMELOCK_ROLE);

Parameters

NameTypeDescription
basketaddressAddress of the basket token.
managementFee_uint16Management fee in BPS denominated in 1e4.

setSwapFee

Set the swap fee to be given to the treasury on rebalance.

Only callable by the timelock.

function setSwapFee(uint16 swapFee_) external onlyRole(_TIMELOCK_ROLE);

Parameters

NameTypeDescription
swapFee_uint16Swap fee in BPS denominated in 1e4.

collectSwapFee

Claims the swap fee for the given asset and sends it to protocol treasury defined in the FeeCollector.

function collectSwapFee(address asset) external onlyRole(_MANAGER_ROLE) returns (uint256 collectedFees);

Parameters

NameTypeDescription
assetaddressAddress of the asset to collect the swap fee for.

updateBitFlag

Updates the bitFlag for the given basket.

function updateBitFlag(address basket, uint256 bitFlag) external onlyRole(_TIMELOCK_ROLE);

Parameters

NameTypeDescription
basketaddressAddress of the basket.
bitFlaguint256New bitFlag. It must be inclusive of the current bitFlag.

pause

PAUSING FUNCTIONS ///

Pauses the contract. Callable by DEFAULT_ADMIN_ROLE or PAUSER_ROLE.

function pause() external;

unpause

Unpauses the contract. Only callable by DEFAULT_ADMIN_ROLE.

function unpause() external onlyRole(DEFAULT_ADMIN_ROLE);

Events

SwapFeeSet

EVENTS ///

Emitted when the swap fee is set.

event SwapFeeSet(uint16 oldFee, uint16 newFee);

ManagementFeeSet

Emitted when the management fee is set.

event ManagementFeeSet(address indexed basket, uint16 oldFee, uint16 newFee);

TokenSwapAdapterSet

Emitted when the TokenSwapAdapter contract is set.

event TokenSwapAdapterSet(address oldAdapter, address newAdapter);

BasketCreated

Emitted when a new basket is created.

event BasketCreated(
    address indexed basket, string basketName, string symbol, address baseAsset, uint256 bitFlag, address strategy
);

BasketBitFlagUpdated

Emitted when the bitFlag of a basket is updated.

event BasketBitFlagUpdated(
    address indexed basket, uint256 oldBitFlag, uint256 newBitFlag, bytes32 oldId, bytes32 newId
);

TokenSwapProposed

Emitted when a token swap is proposed during a rebalance.

event TokenSwapProposed(uint40 indexed epoch, InternalTrade[] internalTrades, ExternalTrade[] externalTrades);

TokenSwapExecuted

Emitted when a token swap is executed during a rebalance.

event TokenSwapExecuted(uint40 indexed epoch);

Errors

TokenSwapNotProposed

ERRORS ///

Thrown when attempting to execute a token swap without first proposing it.

error TokenSwapNotProposed();

ExecuteTokenSwapFailed

Thrown when the call to TokenSwapAdapter.executeTokenSwap fails.

error ExecuteTokenSwapFailed();

InvalidHash

Thrown when the provided hash does not match the expected hash.

This error is used to validate the integrity of data passed between functions.

error InvalidHash();

ExternalTradesHashMismatch

Thrown when the provided external trades do not match the hash stored during the token swap proposal.

This error prevents executing a token swap with different parameters than originally proposed.

error ExternalTradesHashMismatch();

MustWaitForRebalanceToComplete

Thrown when attempting to perform an action that requires no active rebalance.

Certain actions, like setting the token swap adapter, are disallowed during an active rebalance.

error MustWaitForRebalanceToComplete();

Unauthorized

Thrown when a caller attempts to access a function without proper authorization.

This error is thrown when a caller lacks the required role to perform an action.

error Unauthorized();

InvalidManagementFee

Thrown when attempting to set an invalid management fee.

The management fee must not exceed _MAX_MANAGEMENT_FEE.

error InvalidManagementFee();

InvalidSwapFee

Thrown when attempting to set an invalid swap fee.

The swap fee must not exceed _MAX_SWAP_FEE.

error InvalidSwapFee();

BasketTokenNotFound

Thrown when attempting to perform an action on a non-existent basket token.

This error is thrown when the provided basket token is not in the basketTokenToIndexPlusOne mapping.

error BasketTokenNotFound();

BitFlagMustBeDifferent

error BitFlagMustBeDifferent();

BitFlagMustIncludeCurrent

error BitFlagMustIncludeCurrent();

BitFlagUnsupportedByStrategy

error BitFlagUnsupportedByStrategy();

BasketIdAlreadyExists

error BasketIdAlreadyExists();

BasketToken

Git Source

Inherits: ERC20PluginsUpgradeable, ERC4626Upgradeable, ERC165Upgradeable, IERC7540Operator, IERC7540Deposit, IERC7540Redeem, MulticallUpgradeable, SelfPermit

Manages user deposits and redemptions, which are processed asynchronously by the Basket Manager.

State Variables

_USD_ISO_4217_CODE

LIBRARIES /// CONSTANTS ///

ISO 4217 numeric code for USD, used as a constant address representation

address private constant _USD_ISO_4217_CODE = address(840);

_MANAGEMENT_FEE_DECIMALS

uint16 private constant _MANAGEMENT_FEE_DECIMALS = 1e4;

_MAX_MANAGEMENT_FEE

Maximum management fee (30%) in BPS denominated in 1e4.

uint16 private constant _MAX_MANAGEMENT_FEE = 3000;

isOperator

STATE VARIABLES ///

Operator approval status per controller.

mapping(address controller => mapping(address operator => bool)) public isOperator;

lastDepositRequestId

Last deposit request ID per controller.

mapping(address controller => uint256 requestId) public lastDepositRequestId;

lastRedeemRequestId

Last redemption request ID per controller.

mapping(address controller => uint256 requestId) public lastRedeemRequestId;

_depositRequests

Deposit requests mapped by request ID. Even IDs are for deposits.

mapping(uint256 requestId => DepositRequestStruct) internal _depositRequests;

_redeemRequests

Redemption requests mapped by request ID. Odd IDs are for redemptions.

mapping(uint256 requestId => RedeemRequestStruct) internal _redeemRequests;

basketManager

Address of the BasketManager contract handling deposits and redemptions.

address public basketManager;

nextDepositRequestId

Upcoming deposit request ID.

uint256 public nextDepositRequestId;

nextRedeemRequestId

Upcoming redemption request ID.

uint256 public nextRedeemRequestId;

assetRegistry

Address of the AssetRegistry contract for asset status checks.

address public assetRegistry;

bitFlag

Bitflag representing selected assets.

uint256 public bitFlag;

strategy

Strategy contract address associated with this basket.

address public strategy;

lastManagementFeeHarvestTimestamp

Timestamp of the last management fee harvest.

uint40 public lastManagementFeeHarvestTimestamp;

Functions

constructor

Disables initializer functions.

constructor() payable;

initialize

Initializes the contract.

function initialize(
    IERC20 asset_,
    string memory name_,
    string memory symbol_,
    uint256 bitFlag_,
    address strategy_,
    address assetRegistry_
)
    public
    initializer;

Parameters

NameTypeDescription
asset_IERC20Address of the underlying asset.
name_stringName of the token, prefixed with "CoveBasket-".
symbol_stringSymbol of the token, prefixed with "cb".
bitFlag_uint256Bitflag representing selected assets.
strategy_addressStrategy contract address.
assetRegistry_address

totalAssets

Returns the value of the basket in assets. This will be an estimate as it does not account for other factors that may affect the swap rates.

function totalAssets() public view override returns (uint256);

Returns

NameTypeDescription
<none>uint256The total value of the basket in assets.

getTargetWeights

Returns the target weights for the given epoch.

function getTargetWeights() public view returns (uint64[] memory);

Returns

NameTypeDescription
<none>uint64[]The target weights for the basket.

requestDeposit

ERC7540 LOGIC ///

Transfers assets from owner and submits a request for an asynchronous deposit.

function requestDeposit(uint256 assets, address controller, address owner) public returns (uint256 requestId);

Parameters

NameTypeDescription
assetsuint256The amount of assets to deposit.
controlleraddressThe address of the controller of the position being created.
owneraddressThe address of the owner of the assets being deposited.

pendingDepositRequest

Returns the pending deposit request amount for a controller.

If the epoch has been advanced then the request has been fulfilled and is no longer pending.

function pendingDepositRequest(uint256 requestId, address controller) public view returns (uint256 assets);

Parameters

NameTypeDescription
requestIduint256The id of the request.
controlleraddressThe address of the controller of the deposit request.

Returns

NameTypeDescription
assetsuint256The amount of assets pending deposit.

claimableDepositRequest

Returns the amount of requested assets in Claimable state for the controller with the given requestId.

function claimableDepositRequest(uint256 requestId, address controller) public view returns (uint256 assets);

Parameters

NameTypeDescription
requestIduint256The id of the request.
controlleraddressThe address of the controller.

_claimableDepositRequest

function _claimableDepositRequest(
    uint256 fulfilledShares,
    uint256 depositAssets
)
    internal
    pure
    returns (uint256 assets);

requestRedeem

Requests a redemption of shares from the basket.

function requestRedeem(uint256 shares, address controller, address owner) public returns (uint256 requestId);

Parameters

NameTypeDescription
sharesuint256The amount of shares to redeem.
controlleraddressThe address of the controller of the redeemed shares.
owneraddressThe address of the request owner.

pendingRedeemRequest

Returns the pending redeem request amount for a user.

function pendingRedeemRequest(uint256 requestId, address controller) public view returns (uint256 shares);

Parameters

NameTypeDescription
requestIduint256The id of the request.
controlleraddressThe address of the controller of the redemption request.

Returns

NameTypeDescription
sharesuint256The amount of shares pending redemption.

claimableRedeemRequest

Returns the amount of requested shares in Claimable state for the controller with the given requestId.

function claimableRedeemRequest(uint256 requestId, address controller) public view returns (uint256 shares);

Parameters

NameTypeDescription
requestIduint256The id of the request.
controlleraddressThe address of the controller of the redemption request.

Returns

NameTypeDescription
sharesuint256The amount of shares claimable.

_claimableRedeemRequest

function _claimableRedeemRequest(
    uint256 fulfilledAssets,
    uint256 redeemShares
)
    internal
    pure
    returns (uint256 shares);

fulfillDeposit

Fulfills all pending deposit requests. Only callable by the basket manager. Assets are held by the basket manager. Locks in the rate at which users can claim their shares for deposited assets.

function fulfillDeposit(uint256 shares) public;

Parameters

NameTypeDescription
sharesuint256The amount of shares the deposit was fulfilled with.

setBitFlag

Sets the new bitflag for the basket.

This can only be called by the Basket Manager therefore we assume that the new bitflag is valid.

function setBitFlag(uint256 bitFlag_) public;

Parameters

NameTypeDescription
bitFlag_uint256The new bitflag.

prepareForRebalance

Called by the basket manager to advance the redeem epoch, preventing any further redeem requests for the current epoch. Returns the total amount of assets pending deposit and shares pending redemption. This is called at the first step of the rebalance process regardless of the presence of any pending deposits or redemptions. When there are no pending deposits or redeems, the epoch is not advanced.

This function also records the total amount of shares pending redemption for the current epoch.

function prepareForRebalance(
    uint16 feeBps,
    address feeCollector
)
    external
    returns (uint256 pendingDeposits, uint256 sharesPendingRedemption);

Parameters

NameTypeDescription
feeBpsuint16The management fee in basis points to be harvested.
feeCollectoraddressThe address that will receive the harvested management fee.

Returns

NameTypeDescription
pendingDepositsuint256The total amount of assets pending deposit.
sharesPendingRedemptionuint256The total amount of shares pending redemption.

fulfillRedeem

Fulfills all pending redeem requests. Only callable by the basket manager. Burns the shares which are pending redemption. Locks in the rate at which users can claim their assets for redeemed shares.

prepareForRebalance must be called before this function.

function fulfillRedeem(uint256 assets) public;

Parameters

NameTypeDescription
assetsuint256The amount of assets the redemption was fulfilled with.

totalPendingDeposits

Returns the total amount of assets pending deposit.

function totalPendingDeposits() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256The total pending deposit amount.

totalPendingRedemptions

Returns the total number of shares pending redemption.

function totalPendingRedemptions() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256The total pending redeem amount.

cancelDepositRequest

Cancels a pending deposit request.

function cancelDepositRequest() public;

cancelRedeemRequest

Cancels a pending redeem request.

function cancelRedeemRequest() public;

setOperator

Sets a status for an operator's ability to act on behalf of a controller.

function setOperator(address operator, bool approved) public returns (bool success);

Parameters

NameTypeDescription
operatoraddressThe address of the operator.
approvedboolThe status of the operator.

Returns

NameTypeDescription
successboolTrue if the operator status was set, false otherwise.

_onlySelfOrOperator

Reverts if the controller is not the caller or the operator of the caller.

function _onlySelfOrOperator(address controller) internal view;

_onlyBasketManager

Reverts if the caller is not the Basket Manager.

function _onlyBasketManager() internal view;

share

Returns the address of the share token as per ERC-7575.

For non-multi asset vaults this should always return address(this).

function share() public view returns (address shareTokenAddress);

Returns

NameTypeDescription
shareTokenAddressaddressThe address of the share token.

fallbackRedeemTrigger

FALLBACK REDEEM LOGIC ///

In the event of a failed redemption fulfillment this function is called by the basket manager. Allows users to claim their shares back for a redemption in the future and advances the redemption epoch.

function fallbackRedeemTrigger() public;

claimFallbackShares

Claims shares given for a previous redemption request in the event a redemption fulfillment for a given epoch fails.

function claimFallbackShares(address receiver, address controller) public returns (uint256 shares);

Parameters

NameTypeDescription
receiveraddressThe address to receive the shares.
controlleraddressThe address of the controller of the redemption request.

Returns

NameTypeDescription
sharesuint256The amount of shares claimed.

claimFallbackShares

Allows the caller to claim their own fallback shares.

function claimFallbackShares() public returns (uint256 shares);

Returns

NameTypeDescription
sharesuint256The amount of shares claimed.

claimableFallbackShares

Returns the amount of shares claimable for a given user in the event of a failed redemption fulfillment.

function claimableFallbackShares(address controller) public view returns (uint256 shares);

Parameters

NameTypeDescription
controlleraddressThe address of the controller.

Returns

NameTypeDescription
sharesuint256The amount of shares claimable by the controller.

proRataRedeem

Immediately redeems shares for all assets associated with this basket. This is synchronous and does not require the rebalance process to be completed.

function proRataRedeem(uint256 shares, address to, address from) public;

Parameters

NameTypeDescription
sharesuint256Number of shares to redeem.
toaddressAddress to receive the assets.
fromaddressAddress to redeem shares from.

_harvestManagementFee

function _harvestManagementFee(uint16 feeBps, address feeCollector) internal;

deposit

ERC4626 OVERRIDDEN LOGIC ///

Transfers a user's shares owed for a previously fulfillled deposit request.

function deposit(uint256 assets, address receiver, address controller) public returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256The amount of assets previously requested for deposit.
receiveraddressThe address to receive the shares.
controlleraddressThe address of the controller of the deposit request.

Returns

NameTypeDescription
sharesuint256The amount of shares minted.

deposit

Transfers a user's shares owed for a previously fulfillled deposit request.

function deposit(uint256 assets, address receiver) public override returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256The amount of assets to be claimed.
receiveraddressThe address to receive the assets.

Returns

NameTypeDescription
sharesuint256The amount of shares previously requested for redemption.

mint

Transfers a user's shares owed for a previously fulfillled deposit request.

Deposit should be used in all instances instead.

function mint(uint256 shares, address receiver, address controller) public returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256The amount of shares to receive.
receiveraddressThe address to receive the shares.
controlleraddressThe address of the controller of the deposit request.

Returns

NameTypeDescription
assetsuint256The amount of assets previously requested for deposit.

mint

Transfers a user's shares owed for a previously fulfillled deposit request.

function mint(uint256 shares, address receiver) public override returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256The amount of shares to receive.
receiveraddressThe address to receive the shares.

Returns

NameTypeDescription
assetsuint256The amount of assets previously requested for deposit.

_claimDeposit

Internal function to claim deposit for a given amount of assets and shares.

function _claimDeposit(
    DepositRequestStruct storage depositRequest,
    uint256 assets,
    uint256 shares,
    address receiver,
    address controller
)
    internal;

Parameters

NameTypeDescription
depositRequestDepositRequestStruct
assetsuint256The amount of assets to claim.
sharesuint256The amount of shares to claim.
receiveraddressThe address of the receiver of the claimed assets.
controlleraddressThe address of the controller of the deposit request.

withdraw

Transfers a user's assets owed for a previously fulfillled redemption request.

Redeem should be used in all instances instead.

function withdraw(uint256 assets, address receiver, address controller) public override returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256The amount of assets to be claimed.
receiveraddressThe address to receive the assets.
controlleraddressThe address of the controller of the redeem request.

Returns

NameTypeDescription
sharesuint256The amount of shares previously requested for redemption.

redeem

Transfers the receiver assets owed for a fulfilled redeem request.

function redeem(uint256 shares, address receiver, address controller) public override returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256The amount of shares to be claimed.
receiveraddressThe address to receive the assets.
controlleraddressThe address of the controller of the redeem request.

Returns

NameTypeDescription
assetsuint256The amount of assets previously requested for redemption.

_claimRedemption

Internal function to claim redemption for a given amount of assets and shares.

function _claimRedemption(
    RedeemRequestStruct storage redeemRequest,
    uint256 assets,
    uint256 shares,
    address receiver,
    address controller
)
    internal;

Parameters

NameTypeDescription
redeemRequestRedeemRequestStruct
assetsuint256The amount of assets to claim.
sharesuint256The amount of shares to claim.
receiveraddressThe address of the receiver of the claimed assets.
controlleraddressThe address of the controller of the redemption request.

maxWithdraw

Returns an controller's amount of assets fulfilled for redemption.

For requests yet to be fulfilled, this will return 0.

function maxWithdraw(address controller) public view override returns (uint256);

Parameters

NameTypeDescription
controlleraddressThe address of the controller.

Returns

NameTypeDescription
<none>uint256The amount of assets that can be withdrawn.

_maxWithdraw

function _maxWithdraw(
    uint256 fulfilledAssets,
    uint256 redeemShares,
    uint256 totalRedeemShares
)
    internal
    pure
    returns (uint256);

maxRedeem

Returns an controller's amount of shares fulfilled for redemption.

For requests yet to be fulfilled, this will return 0.

function maxRedeem(address controller) public view override returns (uint256);

Parameters

NameTypeDescription
controlleraddressThe address of the controller.

Returns

NameTypeDescription
<none>uint256The amount of shares that can be redeemed.

maxDeposit

Returns an controller's amount of assets fulfilled for deposit.

For requests yet to be fulfilled, this will return 0.

function maxDeposit(address controller) public view override returns (uint256);

Parameters

NameTypeDescription
controlleraddressThe address of the controller.

Returns

NameTypeDescription
<none>uint256The amount of assets that can be deposited.

maxMint

Returns an controller's amount of shares fulfilled for deposit.

For requests yet to be fulfilled, this will return 0.

function maxMint(address controller) public view override returns (uint256);

Parameters

NameTypeDescription
controlleraddressThe address of the controller.

Returns

NameTypeDescription
<none>uint256The amount of shares that can be minted.

_maxMint

function _maxMint(
    uint256 fulfilledShares,
    uint256 depositAssets,
    uint256 totalDepositAssets
)
    internal
    pure
    returns (uint256);

previewDeposit

function previewDeposit(uint256) public pure override returns (uint256);

previewMint

function previewMint(uint256) public pure override returns (uint256);

previewWithdraw

function previewWithdraw(uint256) public pure override returns (uint256);

previewRedeem

function previewRedeem(uint256) public pure override returns (uint256);

fallbackTriggered

Returns true if the redemption request's fallback has been triggered.

function fallbackTriggered(uint256 requestId) public view returns (bool);

Parameters

NameTypeDescription
requestIduint256The id of the request.

Returns

NameTypeDescription
<none>boolTrue if the fallback has been triggered, false otherwise.

supportsInterface

Checks if the contract supports the given interface.

function supportsInterface(bytes4 interfaceID) public view virtual override returns (bool);

Parameters

NameTypeDescription
interfaceIDbytes4The interface ID.

Returns

NameTypeDescription
<none>boolTrue if the contract supports the interface, false otherwise.

_update

Override to call the ERC20PluginsUpgradeable's _update function.

function _update(
    address from,
    address to,
    uint256 amount
)
    internal
    override(ERC20PluginsUpgradeable, ERC20Upgradeable);

balanceOf

Override to call the ERC20PluginsUpgradeable's balanceOf function. See IERC20-balanceOf.

function balanceOf(address account)
    public
    view
    override(ERC20PluginsUpgradeable, ERC20Upgradeable, IERC20)
    returns (uint256);

decimals

Override to use ERC4626's decimals function. See IERC20Metadata-decimals.

function decimals() public view override(ERC20Upgradeable, ERC4626Upgradeable) returns (uint8);

Events

ManagementFeeHarvested

EVENTS ///

Emitted when the management fee is harvested.

event ManagementFeeHarvested(uint256 fee);

Parameters

NameTypeDescription
feeuint256The amount of the management fee harvested.

DepositFulfilled

Emitted when a deposit request is fulfilled and assets are transferred to the user.

event DepositFulfilled(uint256 indexed requestId, uint256 assets, uint256 shares);

Parameters

NameTypeDescription
requestIduint256The unique identifier of the deposit request.
assetsuint256The amount of assets that were deposited.
sharesuint256The number of shares minted for the deposit.

RedeemFulfilled

Emitted when a redemption request is fulfilled and shares are burned.

event RedeemFulfilled(uint256 indexed requestId, uint256 shares, uint256 assets);

Parameters

NameTypeDescription
requestIduint256The unique identifier of the redemption request.
sharesuint256The number of shares redeemed.
assetsuint256The amount of assets returned to the user.

BitFlagUpdated

Emitted when the bitflag is updated to a new value.

event BitFlagUpdated(uint256 oldBitFlag, uint256 newBitFlag);

Parameters

NameTypeDescription
oldBitFlaguint256The previous bitflag value.
newBitFlaguint256The new bitflag value.

Errors

ZeroPendingDeposits

ERRORS ///

Thrown when there are no pending deposits to fulfill.

error ZeroPendingDeposits();

ZeroPendingRedeems

Thrown when there are no pending redeems to fulfill.

error ZeroPendingRedeems();

AssetPaused

Thrown when attempting to request a deposit or redeem while one or more of the basket's assets are paused in the AssetRegistry.

error AssetPaused();

MustClaimOutstandingDeposit

Thrown when attempting to request a new deposit while the user has an outstanding claimable deposit from a previous request. The user must first claim the outstanding deposit.

error MustClaimOutstandingDeposit();

MustClaimOutstandingRedeem

Thrown when attempting to request a new redeem while the user has an outstanding claimable redeem from a previous request. The user must first claim the outstanding redeem.

error MustClaimOutstandingRedeem();

MustClaimFullAmount

Thrown when attempting to claim a partial amount of an outstanding deposit or redeem. The user must claim the full claimable amount.

error MustClaimFullAmount();

CannotFulfillWithZeroShares

Thrown when the basket manager attempts to fulfill a deposit request with zero shares.

error CannotFulfillWithZeroShares();

CannotFulfillWithZeroAssets

Thrown when the basket manager attempts to fulfill a redeem request with zero assets.

error CannotFulfillWithZeroAssets();

ZeroClaimableFallbackShares

Thrown when attempting to claim fallback shares when none are available.

error ZeroClaimableFallbackShares();

NotAuthorizedOperator

Thrown when a non-authorized address attempts to request a deposit or redeem on behalf of another user who has not approved them as an operator.

error NotAuthorizedOperator();

NotBasketManager

Thrown when an address other than the basket manager attempts to call a basket manager only function.

error NotBasketManager();

InvalidManagementFee

Thrown when attempting to set an invalid management fee percentage greater than the maximum allowed.

error InvalidManagementFee();

DepositRequestAlreadyFulfilled

Thrown when the basket manager attempts to fulfill a deposit request that has already been fulfilled.

error DepositRequestAlreadyFulfilled();

RedeemRequestAlreadyFulfilled

Thrown when the basket manager attempts to fulfill a redeem request that has already been fulfilled.

error RedeemRequestAlreadyFulfilled();

RedeemRequestAlreadyFallbacked

Thrown when the basket manager attempts to trigger the fallback for a redeem request that has already been put in fallback state.

error RedeemRequestAlreadyFallbacked();

PreviousDepositRequestNotFulfilled

Thrown when attempting to prepare for a new rebalance before the previous epoch's deposit request has been fulfilled.

error PreviousDepositRequestNotFulfilled();

PreviousRedeemRequestNotFulfilled

Thrown when attempting to prepare for a new rebalance before the previous epoch's redeem request has been fulfilled or put in fallback state.

error PreviousRedeemRequestNotFulfilled();

Structs

DepositRequestStruct

Struct representing a deposit request.

struct DepositRequestStruct {
    mapping(address controller => uint256 assets) depositAssets;
    uint256 totalDepositAssets;
    uint256 fulfilledShares;
}

RedeemRequestStruct

Struct representing a redeem request.

struct RedeemRequestStruct {
    mapping(address controller => uint256 shares) redeemShares;
    uint256 totalRedeemShares;
    uint256 fulfilledAssets;
    bool fallbackTriggered;
}

FeeCollector

Git Source

Inherits: AccessControlEnumerable

Contract to collect fees from the BasketManager and distribute them to sponsors and the protocol treasury

State Variables

_BASKET_TOKEN_ROLE

CONSTANTS ///

bytes32 private constant _BASKET_TOKEN_ROLE = keccak256("BASKET_TOKEN_ROLE");

_FEE_SPLIT_DECIMALS

Fee split is denominated in 1e4. Also used as maximum fee split for the sponsor.

uint16 private constant _FEE_SPLIT_DECIMALS = 1e4;

protocolTreasury

STATE VARIABLES ///

The address of the protocol treasury

address public protocolTreasury;

_basketManager

The BasketManager contract

BasketManager internal immutable _basketManager;

basketTokenSponsors

Mapping of basket tokens to their sponsor addresses

mapping(address basketToken => address sponsor) public basketTokenSponsors;

basketTokenSponsorSplits

Mapping of basket tokens to their sponsor split percentages

mapping(address basketToken => uint16 sponsorSplit) public basketTokenSponsorSplits;

claimableTreasuryFees

Mapping of basket tokens to current claimable treasury fees

mapping(address basketToken => uint256 claimableFees) public claimableTreasuryFees;

claimableSponsorFees

Mapping of basket tokens to the current claimable sponsor fees

mapping(address basketToken => uint256 claimableFees) public claimableSponsorFees;

Functions

constructor

Constructor to set the admin, basket manager, and protocol treasury

constructor(address admin, address basketManager, address treasury) payable;

Parameters

NameTypeDescription
adminaddressThe address of the admin
basketManageraddressThe address of the BasketManager
treasuryaddressThe address of the protocol treasury

setProtocolTreasury

Set the protocol treasury address

function setProtocolTreasury(address treasury) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
treasuryaddressThe address of the new protocol treasury

setSponsor

Set the sponsor for a given basket token

function setSponsor(address basketToken, address sponsor) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
basketTokenaddressThe address of the basket token
sponsoraddressThe address of the sponsor

setSponsorSplit

Set the split of management fees given to the sponsor for a given basket token

function setSponsorSplit(address basketToken, uint16 sponsorSplit) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
basketTokenaddressThe address of the basket token
sponsorSplituint16The percentage of fees to give to the sponsor denominated in _FEE_SPLIT_DECIMALS

notifyHarvestFee

Notify the FeeCollector of the fees collected from the basket token

function notifyHarvestFee(uint256 shares) external;

Parameters

NameTypeDescription
sharesuint256The amount of shares collected

claimSponsorFee

Claim the sponsor fee for a given basket token, only callable by the sponsor

function claimSponsorFee(address basketToken) external;

Parameters

NameTypeDescription
basketTokenaddressThe address of the basket token

claimTreasuryFee

Claim the treasury fee for a given basket token, only callable by the protocol treasury or admin

function claimTreasuryFee(address basketToken) external;

Parameters

NameTypeDescription
basketTokenaddressThe address of the basket token

_checkIfBasketToken

function _checkIfBasketToken(address token) internal view;

Events

SponsorSet

EVENTS ///

Emitted when the sponsor for a basket token is set.

event SponsorSet(address indexed basketToken, address indexed sponsor);

Parameters

NameTypeDescription
basketTokenaddressThe address of the basket token.
sponsoraddressThe address of the sponsor that was set.

SponsorSplitSet

Emitted when the sponsor fee split for a basket token is set.

event SponsorSplitSet(address indexed basketToken, uint16 sponsorSplit);

Parameters

NameTypeDescription
basketTokenaddressThe address of the basket token.
sponsorSplituint16The percentage of fees allocated to the sponsor, denominated in _FEE_SPLIT_DECIMALS.

TreasurySet

Emitted when the protocol treasury address is set.

event TreasurySet(address indexed treasury);

Parameters

NameTypeDescription
treasuryaddressThe address of the new protocol treasury.

Errors

SponsorSplitTooHigh

ERRORS ///

Thrown when attempting to set a sponsor fee split higher than _MAX_FEE.

error SponsorSplitTooHigh();

NoSponsor

Thrown when attempting to set a sponsor fee split for a basket token with no sponsor.

error NoSponsor();

Unauthorized

Thrown when an unauthorized address attempts to call a restricted function.

error Unauthorized();

NotBasketToken

Thrown when attempting to perform an action on an address that is not a basket token.

error NotBasketToken();

NotTreasury

Thrown when attempting to claim treasury fees from an address that is not the protocol treasury.

error NotTreasury();