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 --fork-url <rpc_url> --fork-block-number <block_num> --auto-impersonate

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

Then in another terminal session:

# Deploy contracts to local fork network
pnpm deployLocal

This command uses the deployLocal script defined in package.json. It sets the DEPLOYMENT_CONTEXT to 1-fork and runs the forge script script/Deployments.s.sol with the specified RPC URL, broadcasting the transactions, and syncing the deployment using forge-deploy. The sender address set to COVE_DEPLOYER and is unlocked for local deployment.

  • 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

Permit2Lib

Git Source

Enables efficient transfers and EIP-2612/DAI permits for any token by falling back to Permit2.

State Variables

DAI_DOMAIN_SEPARATOR

The unique EIP-712 domain domain separator for the DAI token contract.

bytes32 internal constant DAI_DOMAIN_SEPARATOR = 0xdbb8cf42e1ecb028be3f3dbc922e1d878b963f411dc388ced501601c60f7c6f7;

WETH9_ADDRESS

The address for the WETH9 contract on Ethereum mainnet, encoded as a bytes32.

bytes32 internal constant WETH9_ADDRESS = 0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2;

PERMIT2

The address of the Permit2 contract the library will use.

IAllowanceTransfer internal constant PERMIT2 = IAllowanceTransfer(address(0x000000000022D473030F116dDEE9F6B43aC78BA3));

Functions

transferFrom2

Transfer a given amount of tokens from one user to another.

function transferFrom2(IERC20 token, address from, address to, uint256 amount) internal;

Parameters

NameTypeDescription
tokenIERC20The token to transfer.
fromaddressThe user to transfer from.
toaddressThe user to transfer to.
amountuint256The amount to transfer.

permit2

Permit a user to spend a given amount of another user's tokens via native EIP-2612 permit if possible, falling back to Permit2 if native permit fails or is not implemented on the token.

function permit2(
    IERC20 token,
    address owner,
    address spender,
    uint256 amount,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
)
    internal;

Parameters

NameTypeDescription
tokenIERC20The token to permit spending.
owneraddressThe user to permit spending from.
spenderaddressThe user to permit spending to.
amountuint256The amount to permit spending.
deadlineuint256The timestamp after which the signature is no longer valid.
vuint8Must produce valid secp256k1 signature from the owner along with r and s.
rbytes32Must produce valid secp256k1 signature from the owner along with v and s.
sbytes32Must produce valid secp256k1 signature from the owner along with r and v.

simplePermit2

Simple unlimited permit on the Permit2 contract.

function simplePermit2(
    IERC20 token,
    address owner,
    address spender,
    uint256 amount,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
)
    internal;

Parameters

NameTypeDescription
tokenIERC20The token to permit spending.
owneraddressThe user to permit spending from.
spenderaddressThe user to permit spending to.
amountuint256The amount to permit spending.
deadlineuint256The timestamp after which the signature is no longer valid.
vuint8Must produce valid secp256k1 signature from the owner along with r and s.
rbytes32Must produce valid secp256k1 signature from the owner along with v and s.
sbytes32Must produce valid secp256k1 signature from the owner along with r and v.

SafeCast160

Git Source

Functions

toUint160

Safely casts uint256 to uint160

function toUint160(uint256 value) internal pure returns (uint160);

Parameters

NameTypeDescription
valueuint256The uint256 to be cast

Errors

UnsafeCast

Thrown when a valude greater than type(uint160).max is cast to uint160

error UnsafeCast();

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

Contents

IAllowanceTransfer

Git Source

Inherits: IEIP712

Handles ERC20 token permissions through signature based allowance setting and ERC20 token transfers by checking allowed amounts

Requires user's token approval on the Permit2 contract

Functions

allowance

A mapping from owner address to token address to spender address to PackedAllowance struct, which contains details and conditions of the approval.

The mapping is indexed in the above order see: allowance[ownerAddress][tokenAddress][spenderAddress]

The packed slot holds the allowed amount, expiration at which the allowed amount is no longer valid, and current nonce that's updated on any signature based approvals.

function allowance(
    address user,
    address token,
    address spender
)
    external
    view
    returns (uint160 amount, uint48 expiration, uint48 nonce);

approve

Approves the spender to use up to amount of the specified token up until the expiration

The packed allowance also holds a nonce, which will stay unchanged in approve

Setting amount to type(uint160).max sets an unlimited approval

function approve(address token, address spender, uint160 amount, uint48 expiration) external;

Parameters

NameTypeDescription
tokenaddressThe token to approve
spenderaddressThe spender address to approve
amountuint160The approved amount of the token
expirationuint48The timestamp at which the approval is no longer valid

permit

Permit a spender to a given amount of the owners token via the owner's EIP-712 signature

May fail if the owner's nonce was invalidated in-flight by invalidateNonce

function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external;

Parameters

NameTypeDescription
owneraddressThe owner of the tokens being approved
permitSinglePermitSingleData signed over by the owner specifying the terms of approval
signaturebytesThe owner's signature over the permit data

permit

Permit a spender to the signed amounts of the owners tokens via the owner's EIP-712 signature

May fail if the owner's nonce was invalidated in-flight by invalidateNonce

function permit(address owner, PermitBatch memory permitBatch, bytes calldata signature) external;

Parameters

NameTypeDescription
owneraddressThe owner of the tokens being approved
permitBatchPermitBatchData signed over by the owner specifying the terms of approval
signaturebytesThe owner's signature over the permit data

transferFrom

Transfer approved tokens from one address to another

Requires the from address to have approved at least the desired amount of tokens to msg.sender.

function transferFrom(address from, address to, uint160 amount, address token) external;

Parameters

NameTypeDescription
fromaddressThe address to transfer from
toaddressThe address of the recipient
amountuint160The amount of the token to transfer
tokenaddressThe token address to transfer

transferFrom

Transfer approved tokens in a batch

Requires the from addresses to have approved at least the desired amount of tokens to msg.sender.

function transferFrom(AllowanceTransferDetails[] calldata transferDetails) external;

Parameters

NameTypeDescription
transferDetailsAllowanceTransferDetails[]Array of owners, recipients, amounts, and tokens for the transfers

lockdown

Enables performing a "lockdown" of the sender's Permit2 identity by batch revoking approvals

function lockdown(TokenSpenderPair[] calldata approvals) external;

Parameters

NameTypeDescription
approvalsTokenSpenderPair[]Array of approvals to revoke.

invalidateNonces

Invalidate nonces for a given (token, spender) pair

Can't invalidate more than 2**16 nonces per transaction.

function invalidateNonces(address token, address spender, uint48 newNonce) external;

Parameters

NameTypeDescription
tokenaddressThe token to invalidate nonces for
spenderaddressThe spender to invalidate nonces for
newNonceuint48The new nonce to set. Invalidates all nonces less than it.

Events

NonceInvalidation

Emits an event when the owner successfully invalidates an ordered nonce.

event NonceInvalidation(
    address indexed owner, address indexed token, address indexed spender, uint48 newNonce, uint48 oldNonce
);

Approval

Emits an event when the owner successfully sets permissions on a token for the spender.

event Approval(
    address indexed owner, address indexed token, address indexed spender, uint160 amount, uint48 expiration
);

Permit

Emits an event when the owner successfully sets permissions using a permit signature on a token for the spender.

event Permit(
    address indexed owner,
    address indexed token,
    address indexed spender,
    uint160 amount,
    uint48 expiration,
    uint48 nonce
);

Lockdown

Emits an event when the owner sets the allowance back to 0 with the lockdown function.

event Lockdown(address indexed owner, address token, address spender);

Errors

AllowanceExpired

Thrown when an allowance on a token has expired.

error AllowanceExpired(uint256 deadline);

Parameters

NameTypeDescription
deadlineuint256The timestamp at which the allowed amount is no longer valid

InsufficientAllowance

Thrown when an allowance on a token has been depleted.

error InsufficientAllowance(uint256 amount);

Parameters

NameTypeDescription
amountuint256The maximum amount allowed

ExcessiveInvalidation

Thrown when too many nonces are invalidated.

error ExcessiveInvalidation();

Structs

PermitDetails

The permit data for a token

struct PermitDetails {
    address token;
    uint160 amount;
    uint48 expiration;
    uint48 nonce;
}

PermitSingle

The permit message signed for a single token allowance

struct PermitSingle {
    PermitDetails details;
    address spender;
    uint256 sigDeadline;
}

PermitBatch

The permit message signed for multiple token allowances

struct PermitBatch {
    PermitDetails[] details;
    address spender;
    uint256 sigDeadline;
}

PackedAllowance

The saved permissions

This info is saved per owner, per token, per spender and all signed over in the permit message

Setting amount to type(uint160).max sets an unlimited approval

struct PackedAllowance {
    uint160 amount;
    uint48 expiration;
    uint48 nonce;
}

TokenSpenderPair

A token spender pair.

struct TokenSpenderPair {
    address token;
    address spender;
}

AllowanceTransferDetails

Details for a token transfer.

struct AllowanceTransferDetails {
    address from;
    address to;
    uint160 amount;
    address token;
}

IDAIPermit

Git Source

Functions

permit

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 owner.
spenderaddressThe address of the token spender.
nonceuint256The owner'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 owner along with r and s.
rbytes32Must produce valid secp256k1 signature from the owner along with v and s.
sbytes32Must produce valid secp256k1 signature from the owner along with r and v.

nonces

function nonces(address holder) external view returns (uint256);

Parameters

NameTypeDescription
holderaddressThe address of the token owner.

IEIP712

Git Source

Functions

DOMAIN_SEPARATOR

function DOMAIN_SEPARATOR() external view returns (bytes32);

IPermit2

Git Source

Inherits: ISignatureTransfer, IAllowanceTransfer

Permit2 handles signature-based transfers in SignatureTransfer and allowance-based transfers in AllowanceTransfer.

Users must approve Permit2 before calling any of the transfer functions.

ISignatureTransfer

Git Source

Inherits: IEIP712

Handles ERC20 token transfers through signature based actions

Requires user's token approval on the Permit2 contract

Functions

nonceBitmap

A map from token owner address and a caller specified word index to a bitmap. Used to set bits in the bitmap to prevent against signature replay protection

Uses unordered nonces so that permit messages do not need to be spent in a certain order

The mapping is indexed first by the token owner, then by an index specified in the nonce

It returns a uint256 bitmap

The index, or wordPosition is capped at type(uint248).max

function nonceBitmap(address, uint256) external view returns (uint256);

permitTransferFrom

Transfers a token using a signed permit message

Reverts if the requested amount is greater than the permitted signed amount

function permitTransferFrom(
    PermitTransferFrom memory permit,
    SignatureTransferDetails calldata transferDetails,
    address owner,
    bytes calldata signature
)
    external;

Parameters

NameTypeDescription
permitPermitTransferFromThe permit data signed over by the owner
transferDetailsSignatureTransferDetailsThe spender's requested transfer details for the permitted token
owneraddressThe owner of the tokens to transfer
signaturebytesThe signature to verify

permitWitnessTransferFrom

Transfers a token using a signed permit message

Includes extra data provided by the caller to verify signature over

The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition

Reverts if the requested amount is greater than the permitted signed amount

function permitWitnessTransferFrom(
    PermitTransferFrom memory permit,
    SignatureTransferDetails calldata transferDetails,
    address owner,
    bytes32 witness,
    string calldata witnessTypeString,
    bytes calldata signature
)
    external;

Parameters

NameTypeDescription
permitPermitTransferFromThe permit data signed over by the owner
transferDetailsSignatureTransferDetailsThe spender's requested transfer details for the permitted token
owneraddressThe owner of the tokens to transfer
witnessbytes32Extra data to include when checking the user signature
witnessTypeStringstringThe EIP-712 type definition for remaining string stub of the typehash
signaturebytesThe signature to verify

permitTransferFrom

Transfers multiple tokens using a signed permit message

function permitTransferFrom(
    PermitBatchTransferFrom memory permit,
    SignatureTransferDetails[] calldata transferDetails,
    address owner,
    bytes calldata signature
)
    external;

Parameters

NameTypeDescription
permitPermitBatchTransferFromThe permit data signed over by the owner
transferDetailsSignatureTransferDetails[]Specifies the recipient and requested amount for the token transfer
owneraddressThe owner of the tokens to transfer
signaturebytesThe signature to verify

permitWitnessTransferFrom

Transfers multiple tokens using a signed permit message

Includes extra data provided by the caller to verify signature over

The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition

function permitWitnessTransferFrom(
    PermitBatchTransferFrom memory permit,
    SignatureTransferDetails[] calldata transferDetails,
    address owner,
    bytes32 witness,
    string calldata witnessTypeString,
    bytes calldata signature
)
    external;

Parameters

NameTypeDescription
permitPermitBatchTransferFromThe permit data signed over by the owner
transferDetailsSignatureTransferDetails[]Specifies the recipient and requested amount for the token transfer
owneraddressThe owner of the tokens to transfer
witnessbytes32Extra data to include when checking the user signature
witnessTypeStringstringThe EIP-712 type definition for remaining string stub of the typehash
signaturebytesThe signature to verify

invalidateUnorderedNonces

Invalidates the bits specified in mask for the bitmap at the word position

The wordPos is maxed at type(uint248).max

function invalidateUnorderedNonces(uint256 wordPos, uint256 mask) external;

Parameters

NameTypeDescription
wordPosuint256A number to index the nonceBitmap at
maskuint256A bitmap masked against msg.sender's current bitmap at the word position

Events

UnorderedNonceInvalidation

Emits an event when the owner successfully invalidates an unordered nonce.

event UnorderedNonceInvalidation(address indexed owner, uint256 word, uint256 mask);

Errors

InvalidAmount

Thrown when the requested amount for a transfer is larger than the permissioned amount

error InvalidAmount(uint256 maxAmount);

Parameters

NameTypeDescription
maxAmountuint256The maximum amount a spender can request to transfer

LengthMismatch

Thrown when the number of tokens permissioned to a spender does not match the number of tokens being transferred

If the spender does not need to transfer the number of tokens permitted, the spender can request amount 0 to be transferred

error LengthMismatch();

Structs

TokenPermissions

The token and amount details for a transfer signed in the permit transfer signature

struct TokenPermissions {
    address token;
    uint256 amount;
}

PermitTransferFrom

The signed permit message for a single token transfer

struct PermitTransferFrom {
    TokenPermissions permitted;
    uint256 nonce;
    uint256 deadline;
}

SignatureTransferDetails

Specifies the recipient address and amount for batched transfers.

Recipients and amounts correspond to the index of the signed token permissions array.

Reverts if the requested amount is greater than the permitted signed amount.

struct SignatureTransferDetails {
    address to;
    uint256 requestedAmount;
}

PermitBatchTransferFrom

Used to reconstruct the signed permit message for multiple token transfers

Do not need to pass in spender address as it is required that it is msg.sender

Note that a user still signs over a spender address

struct PermitBatchTransferFrom {
    TokenPermissions[] permitted;
    uint256 nonce;
    uint256 deadline;
}

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

aggregator

function aggregator() external view returns (address);

IPriceOracleWithBaseAndQuote

Git Source

Inherits: IPriceOracle

Functions

base

function base() external view returns (address);

quote

function quote() external view returns (address);

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

IMasterRegistry

Git Source

Functions

addRegistry

Add a new registry entry to the master list. Reverts if an entry is already found with the given name.

function addRegistry(bytes32 registryName, address registryAddress) external;

Parameters

NameTypeDescription
registryNamebytes32name for the registry
registryAddressaddressaddress of the new registry

updateRegistry

Update an existing registry entry to the master list. Reverts if no match is found.

function updateRegistry(bytes32 registryName, address registryAddress) external;

Parameters

NameTypeDescription
registryNamebytes32name for the registry
registryAddressaddressaddress of the new registry

resolveNameToLatestAddress

Resolves a name to the latest registry address. Reverts if no match is found.

function resolveNameToLatestAddress(bytes32 registryName) external view returns (address);

Parameters

NameTypeDescription
registryNamebytes32name for the registry

Returns

NameTypeDescription
<none>addressaddress address of the latest registry with the matching name

resolveNameAndVersionToAddress

Resolves a name and version to an address. Reverts if there is no registry with given name and version.

function resolveNameAndVersionToAddress(bytes32 registryName, uint256 version) external view returns (address);

Parameters

NameTypeDescription
registryNamebytes32address of the registry you want to resolve to
versionuint256version of the registry you want to resolve to

resolveNameToAllAddresses

Resolves a name to an array of all addresses. Reverts if no match is found.

function resolveNameToAllAddresses(bytes32 registryName) external view returns (address[] memory);

Parameters

NameTypeDescription
registryNamebytes32name for the registry

Returns

NameTypeDescription
<none>address[]address address of the latest registry with the matching name

resolveAddressToRegistryData

Resolves an address to registry entry data.

function resolveAddressToRegistryData(address registryAddress)
    external
    view
    returns (bytes32 registryName, uint256 version, bool isLatest);

Parameters

NameTypeDescription
registryAddressaddressaddress of a registry you want to resolve

Returns

NameTypeDescription
registryNamebytes32name of the resolved registry
versionuint256version of the resolved registry
isLatestboolboolean flag of whether the given address is the latest version of the given registries with matching name

Structs

ReverseRegistryData

struct ReverseRegistryData {
    bytes32 registryName;
    uint256 version;
}

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;

_WEIGHT_PRECISION

Precision used for weight calculations and slippage calculations.

uint256 private constant _WEIGHT_PRECISION = 1e18;

_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,
    address[][] calldata basketAssets
)
    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.
basketAssetsaddress[][]Array of assets in 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,
    address[][] calldata basketAssets
)
    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.
basketAssetsaddress[][]

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.

getAssetIndexInBasket

Returns the index of the asset in a given basket

function getAssetIndexInBasket(
    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[] calldata 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,
    EulerRouter eulerRouter,
    address[] calldata baskets,
    address[][] calldata basketAssets
)
    private;

Parameters

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

_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,
    EulerRouter eulerRouter,
    address[] calldata baskets,
    address[][] calldata basketAssets,
    BasketContext memory slot
)
    private
    view;

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
eulerRouterEulerRouter
basketsaddress[]Array of basket addresses currently being rebalanced.
basketAssetsaddress[][]An array of arrays of basket assets.
slotBasketContextA Slot struct containing the basket balances and total values.

_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,
    EulerRouter eulerRouter,
    InternalTrade[] calldata internalTrades,
    address[] calldata baskets,
    BasketContext memory slot
)
    private;

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
eulerRouterEulerRouter
internalTradesInternalTrade[]Array of internal trades to execute.
basketsaddress[]Array of basket addresses currently being rebalanced.
slotBasketContextA Slot struct containing the basket balances and total values.

_validateExternalTrades

Internal function to validate the results of external trades.

If the result of an external trade is not within the slippageLimit threshold of the minAmount, this function will revert. If the sum of the trade ownerships is not equal to _WEIGHT_PRECISION, this function will revert.

function _validateExternalTrades(
    BasketManagerStorage storage self,
    EulerRouter eulerRouter,
    ExternalTrade[] calldata externalTrades,
    address[] calldata baskets,
    BasketContext memory slot
)
    private
    view;

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
eulerRouterEulerRouter
externalTradesExternalTrade[]Array of external trades to be validated.
basketsaddress[]Array of basket addresses currently being rebalanced.
slotBasketContextA Slot struct containing the basket balances and total values.

_validateBasketHash

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

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

_isTargetWeightMet

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

function _isTargetWeightMet(
    BasketManagerStorage storage self,
    EulerRouter eulerRouter,
    address[] calldata baskets,
    uint64[][] calldata basketsTargetWeights,
    address[][] calldata basketAssets,
    BasketContext memory slot
)
    private
    view
    returns (bool);

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
eulerRouterEulerRouter
basketsaddress[]Array of basket addresses currently being rebalanced.
basketsTargetWeightsuint64[][]Array of target weights for each basket.
basketAssetsaddress[][]Array of assets in each basket.
slotBasketContextA Slot struct containing the basket balances and total values.

_processPendingDeposits

Internal function to process pending deposits and fulfill them.

Assumes pendingDeposit is not 0.

function _processPendingDeposits(
    BasketManagerStorage storage self,
    EulerRouter eulerRouter,
    address basket,
    uint256 totalSupply,
    uint256 basketValue,
    uint256 baseAssetBalance,
    uint256 pendingDeposit,
    address baseAssetAddress
)
    private
    returns (uint256 newShares, uint256 pendingDepositValue);

Parameters

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

Returns

NameTypeDescription
newSharesuint256Amount of new shares minted.
pendingDepositValueuint256Value of the pending deposits in USD.

_calculateBasketValue

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

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

Parameters

NameTypeDescription
selfBasketManagerStorageBasketManagerStorage struct containing strategy data.
eulerRouterEulerRouter
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.

_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,
    address[][] basketAssets,
    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
basketAssetsaddress[][]Array of assets in 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);

Parameters

NameTypeDescription
epochuint40Unique identifier for the rebalance, incremented each time a rebalance is completed

RebalanceRetried

Emitted when a rebalance is retried.

event RebalanceRetried(uint40 indexed epoch, uint256 retryCount);

Parameters

NameTypeDescription
epochuint40Unique identifier for the rebalance, incremented each time a rebalance is completed
retryCountuint256Number of retries for the current rebalance epoch. On the first retry, this will be 1.

Errors

ZeroAddress

ERRORS ///

Reverts when the address is zero.

error ZeroAddress();

ZeroAmount

Reverts when the amount is zero.

error ZeroAmount();

ZeroTotalSupply

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

CannotProposeEmptyTrades

Reverts when no internal or external trades are provided for a rebalance.

error CannotProposeEmptyTrades();

OwnershipSumMismatch

Reverts when the sum of tradeOwnerships do not match the _WEIGHT_PRECISION

error OwnershipSumMismatch();

InternalTradeSellAmountZero

Reverts when the sell amount of an internal trade is zero.

error InternalTradeSellAmountZero();

ExternalTradeSellAmountZero

Reverts when the sell amount of an external trade is zero.

error ExternalTradeSellAmountZero();

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;
    uint256 sellValue;
    uint256 feeValue;
}

BasketContext

Outsource vars to resolve stack too deep during coverage runs

struct BasketContext {
    uint256[][] basketBalances;
    uint256[] totalValues;
}

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.

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

BasicRetryOperator

Git Source

Inherits: ReentrancyGuard, AccessControlEnumerable

A minimal operator contract compatible with Cove's BasketToken. Once approved via BasketToken.setOperator, anyone can call the handler functions to automatically claim a user's fulfilled deposits/redeems (or their fall-backs) and route the resulting assets/shares back to the original user.

State Variables

_retryDisabledFlags

mapping(address user => uint8 flags) private _retryDisabledFlags;

_DEPOSIT_RETRY_DISABLED_FLAG

uint8 private constant _DEPOSIT_RETRY_DISABLED_FLAG = 1 << 0;

_REDEEM_RETRY_DISABLED_FLAG

uint8 private constant _REDEEM_RETRY_DISABLED_FLAG = 1 << 1;

MANAGER_ROLE

bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");

Functions

constructor

Constructor for the BasicRetryOperator.

constructor(address admin, address manager) payable;

Parameters

NameTypeDescription
adminaddressThe address of the admin who can grant and revoke roles.
manageraddressThe address of the manager who can change token approvals.

setDepositRetry

Enable / disable automatic fallback asset claims when deposits cannot be fulfilled.

By default, users are considered opted-in for retry paths.

function setDepositRetry(bool enabled) external;

setRedeemRetry

Enable / disable automatic fallback share claims when redeems cannot be fulfilled.

By default, users are considered opted-in for retry paths.

function setRedeemRetry(bool enabled) external;

isDepositRetryEnabled

Returns whether the deposit retry is enabled for user.

function isDepositRetryEnabled(address user) public view returns (bool);

Returns

NameTypeDescription
<none>booltrue if the deposit retry is enabled for user, false otherwise.

isRedeemRetryEnabled

Returns whether the redeem retry is enabled for user.

function isRedeemRetryEnabled(address user) public view returns (bool);

Returns

NameTypeDescription
<none>booltrue if the redeem retry is enabled for user, false otherwise.

handleDeposit

Claims a fulfilled deposit for user. If nothing is fulfilled and the caller opted-in, attempts to pull fallback assets instead.

function handleDeposit(address user, address basketToken) external nonReentrant;

handleRedeem

Claims a fulfilled redeem for user. If nothing is fulfilled and the caller opted-in, attempts to pull fallback shares instead.

function handleRedeem(address user, address basketToken) external nonReentrant;

approveDeposits

Approves the asset of basketToken to be spent by basketToken.

This is necessary to allow retrying deposits to work without approving the asset beforehand every time. Call this function after the BasketToken is deployed to approve the asset to be spent by the operator. In case the basket token misbehaves, the manager can revoke the approval to prevent the operator from being used.

function approveDeposits(BasketToken basketToken, uint256 amount) external onlyRole(MANAGER_ROLE);

Events

DepositClaimedForUser

Emitted after successfully claiming a user's fulfilled deposit.

event DepositClaimedForUser(address indexed user, address indexed basketToken, uint256 assets, uint256 shares);

Parameters

NameTypeDescription
useraddressThe controller whose fulfilled deposit is being claimed.
basketTokenaddressThe address of the basket token contract the deposit pertains to.
assetsuint256The amount of base assets returned to the user.
sharesuint256The number of basket shares minted to the user.

RedeemClaimedForUser

Emitted after successfully claiming a user's fulfilled redemption.

event RedeemClaimedForUser(address indexed user, address indexed basketToken, uint256 shares, uint256 assets);

Parameters

NameTypeDescription
useraddressThe controller whose fulfilled redeem is being claimed.
basketTokenaddressThe address of the basket token contract the redeem pertains to.
sharesuint256The number of basket shares burned from the user.
assetsuint256The amount of base assets returned to the user.

FallbackAssetsClaimedForUser

Emitted when fallback assets are claimed for a user without retrying the deposit.

event FallbackAssetsClaimedForUser(address indexed user, address indexed basketToken, uint256 assets);

Parameters

NameTypeDescription
useraddressThe controller receiving the fallback assets.
basketTokenaddressThe address of the basket token contract the fallback pertains to.
assetsuint256The amount of base assets sent to the user.

FallbackAssetsRetriedForUser

Emitted when fallback assets are claimed and immediately retried as a new deposit request on behalf of the user.

event FallbackAssetsRetriedForUser(address indexed user, address indexed basketToken, uint256 assets);

Parameters

NameTypeDescription
useraddressThe controller whose fallback assets are being retried.
basketTokenaddressThe address of the basket token contract the fallback pertains to.
assetsuint256The amount of base assets retried for deposit.

FallbackSharesClaimedForUser

Emitted when fallback shares are claimed for a user without retrying the redeem.

event FallbackSharesClaimedForUser(address indexed user, address indexed basketToken, uint256 shares);

Parameters

NameTypeDescription
useraddressThe controller receiving the fallback shares.
basketTokenaddressThe address of the basket token contract the fallback pertains to.
sharesuint256The amount of basket shares sent to the user.

FallbackSharesRetriedForUser

Emitted when fallback shares are claimed and a new redeem request is submitted on behalf of the user.

event FallbackSharesRetriedForUser(address indexed user, address indexed basketToken, uint256 shares);

Parameters

NameTypeDescription
useraddressThe controller whose fallback shares are being retried.
basketTokenaddressThe address of the basket token contract the fallback pertains to.
sharesuint256The amount of basket shares retried for redemption.

DepositRetrySet

Emitted when a user updates their preference for automatically retrying failed deposits.

event DepositRetrySet(address indexed user, bool enabled);

Parameters

NameTypeDescription
useraddressThe user updating the preference.
enabledboolTrue if automatic retry for deposits is enabled, false otherwise.

RedeemRetrySet

Emitted when a user updates their preference for automatically retrying failed redeems.

event RedeemRetrySet(address indexed user, bool enabled);

Parameters

NameTypeDescription
useraddressThe user updating the preference.
enabledboolTrue if automatic retry for redeems is enabled, false otherwise.

Errors

ZeroAddress

Reverts when a provided address is the zero address.

error ZeroAddress();

NothingToClaim

Reverts when there is no fulfilled deposit, no fulfilled redeem, and no fallback amount available to claim.

error NothingToClaim();

Contents

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 This is a modified version of AnchoredOracle.sol that scales the input amount when the primary oracle returns a very small output amount. This implementation is only compatible with underlying oracles that are linearly related to the quote asset. The maximum input amount must be type(uint256).max / 1e18.

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.

Errors

AnchoredOracle_ScalingOverflow

Reverts when the input amount is too large to scale without overflow.

error AnchoredOracle_ScalingOverflow();

ChainedERC4626Oracle

Git Source

Inherits: BaseAdapter

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

A price oracle adapter for chained ERC4626 vault tokens

Handles price conversions between ERC4626 vault shares through multiple levels until reaching the target underlying asset. The oracle automatically converts between share and asset prices through the entire chain using each vault's convertToAssets/convertToShares functions. This oracle relies on the convertToAssets/convertToShares functions of the underlying ERC4626 vaults. If the dependent ERC4626 contracts do not implement sufficient protection against donation attacks, sudden price jumps may occur when large amounts of assets are donated to the vaults without a proportional increase in shares. Users should verify the security measures implemented by the underlying vaults. Due to this risk, this oracle should only be used when there is no direct price feed available for the vault tokens.

State Variables

name

The name of the oracle

string public constant override name = "ChainedERC4626Oracle";

base

The address of the base asset (first vault in chain)

address public immutable base;

quote

The address of the quote asset (final underlying asset)

address public immutable quote;

vaults

The array of vaults in the chain

address[] public vaults;

_MAX_CHAIN_LENGTH

Maximum allowed length for the vault chain

uint256 private constant _MAX_CHAIN_LENGTH = 10;

Functions

constructor

Constructor for the ChainedERC4626Oracle contract

constructor(IERC4626 _initialVault, address _targetAsset) payable;

Parameters

NameTypeDescription
_initialVaultIERC4626The starting ERC4626 vault in the chain
_targetAssetaddressThe final underlying asset to reach

_getQuote

Internal function to get quote through the vault chain

function _getQuote(uint256 inAmount, address _base, address _quote) internal view virtual override returns (uint256);

Parameters

NameTypeDescription
inAmountuint256The input amount to convert
_baseaddressThe base asset address
_quoteaddressThe quote asset address

Returns

NameTypeDescription
<none>uint256The converted amount

Errors

InvalidVaultChain

Thrown when a vault in the chain is invalid (zero address)

error InvalidVaultChain();

ChainTooLong

Thrown when the vault chain is either empty or exceeds the maximum allowed length

error ChainTooLong();

TargetAssetNotReached

Thrown when the chain cannot reach the target asset (e.g., invalid vault sequence)

error TargetAssetNotReached();

CurveEMAOracleUnderlying

Git Source

Inherits: BaseAdapter

Author: Euler Labs (https://www.eulerlabs.com/)

Adapter utilizing the EMA price oracle in Curve pools.

Note: security-contact: security@euler.xyz

State Variables

name

Get the name of the oracle.

string public constant name = "CurveEMAOracleUnderlying";

pool

The address of the Curve pool.

address public immutable pool;

base

The address of the base asset.

address public immutable base;

quote

The address of the quote asset, must be pool.coins[0].

address public immutable quote;

priceOracleIndex

The index in price_oracle corresponding to the base asset.

Note that indices in price_oracle are shifted by 1, i.e. 0 corresponds to coins[1].

uint256 public immutable priceOracleIndex;

_scale

The scale factors used for decimal conversions.

Scale internal immutable _scale;

Functions

constructor

Deploy a CurveEMAOracleUnderlying for a Curve pool.

IMPORTANT: The isBaseUnderlying and isQuoteUnderlying flags must match the pool's actual asset types. For example, in the sUSDE/sfrxUSD pool (0x3bd1017929b43c1414be2aca39892590fba4d6e2), both tokens are ERC4626-compatible, and the pool returns USDE/frxUSD prices. Curve pools with ERC4626-compatible tokens (like sUSDE/sfrxUSD) internally handle underlying asset conversions. The price_oracle() function returns the price in terms of the underlying assets (e.g., USDE/frxUSD). This behavior is pool-specific and depends on the pool's initialization parameters. WARNING: Incorrect configuration of isBaseUnderlying and isQuoteUnderlying will result in incorrect price calculations. Always verify the pool's asset types off-chain before deployment. WARNING: Some StableSwap-NG pools deployed before Dec-12-2023 have a known oracle vulnerability. See (https://docs.curve.fi/stableswap-exchange/stableswap-ng/pools/oracles/#price-oracles) for more details. Additionally, verify that the pool has enough liquidity before deploying this adapter.*

constructor(
    address _pool,
    address _base,
    address _quote,
    uint256 _priceOracleIndex,
    bool isBaseUnderlying,
    bool isQuoteUnderlying
)
    payable;

Parameters

NameTypeDescription
_pooladdressThe address of the Curve pool.
_baseaddressThe address of the base asset.
_quoteaddressThe address of the quote asset, must match pool.coins[0].
_priceOracleIndexuint256The index in price_oracle corresponding to the base asset. If type(uint256).max, then the adapter will call the non-indexed price method price_oracle().
isBaseUnderlyingboolWhether the price oracle returns the price of the base asset in the underlying asset.
isQuoteUnderlyingboolWhether the price oracle returns the price of the quote asset in the underlying asset.

_getQuote

Get a quote by calling the Curve oracle.

function _getQuote(uint256 inAmount, address _base, address _quote) internal view override returns (uint256);

Parameters

NameTypeDescription
inAmountuint256The amount of base to convert.
_baseaddressThe token that is being priced.
_quoteaddressThe token that is the unit of account.

Returns

NameTypeDescription
<none>uint256The converted amount using the Curve EMA oracle.

Errors

BaseAssetMismatch

error BaseAssetMismatch();

QuoteAssetMismatch

error QuoteAssetMismatch();

ERC4626Oracle

Git Source

Inherits: BaseAdapter

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

A price oracle adapter for ERC4626 vault tokens

Handles price conversions between ERC4626 vault shares and their underlying assets. When the vault token is used as the base or quote, the oracle automatically converts between share and asset prices using the vault's convertToAssets/convertToShares functions. The oracle follows the behavior of the ERC4626 vault's implementation of its functions, typically ignoring the maximum amount of shares that can be redeemed or minted. This oracle relies on the convertToAssets/convertToShares functions of the underlying ERC4626 vault. If the dependent ERC4626 contract does not implement sufficient protection against donation attacks, sudden price jumps may occur when large amounts of assets are donated to the vault without a proportional increase in shares. Users should verify the security measures implemented by the underlying vault. Due to this risk, this oracle should only be used when there is no direct price feed available for the vault token.

State Variables

name

The name of the oracle.

string public constant override name = "ERC4626Oracle";

base

The address of the base asset.

address public immutable base;

quote

The address of the quote asset.

address public immutable quote;

Functions

constructor

Constructor for the ERC4626Oracle contract.

constructor(IERC4626 _vault) payable;

Parameters

NameTypeDescription
_vaultIERC4626The ERC4626 vault that should be used as the base asset.

_getQuote

function _getQuote(uint256 inAmount, address _base, address _quote) internal view virtual override returns (uint256);

Contents

FarmingPluginFactory

Git Source

Inherits: AccessControlEnumerable

Deploys new FarmingPlugins and acts as a registry. Roles

  • DEFAULT_ADMIN_ROLE — can grant/revoke all roles and set default plugin owner
  • MANAGER_ROLE — allowed to deploy new farming plugins

This factory uses CREATE2 to deploy the farming plugin, therefore there cannot be two plugins with the same staking token and rewards token.

State Variables

MANAGER_ROLE

Role for managing the factory.

bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");

defaultPluginOwner

Default plugin owner.

address public defaultPluginOwner;

_CREATE3_FACTORY

CREATE3Factory address

CREATE3Factory private constant _CREATE3_FACTORY = CREATE3Factory(0x93FEC2C00BfE902F733B57c5a6CeeD7CD1384AE1);

_plugins

staking token => list of all farming plugins created for that token

mapping(address => address[]) private _plugins;

_allPlugins

flat list of every plugin ever deployed (useful for iteration off-chain)

address[] private _allPlugins;

Functions

constructor

Constructor.

constructor(address admin, address manager, address _defaultPluginOwner) payable;

Parameters

NameTypeDescription
adminaddressAddress that receives DEFAULT_ADMIN_ROLE.
manageraddressAddress that receives MANAGER_ROLE.
_defaultPluginOwneraddressAddress that will be the default plugin owner.

allPlugins

All plugins ever created.

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

Returns

NameTypeDescription
<none>address[]allPlugins Array of all farming plugins.

plugins

Plugins for a given staking token.

function plugins(address stakingToken) external view returns (address[] memory);

Parameters

NameTypeDescription
stakingTokenaddressAddress of the staking token.

Returns

NameTypeDescription
<none>address[]plugins Array of farming plugins for the given staking token.

computePluginAddress

Compute the address of a plugin for a given staking token and rewards token.

The corresponding contract may not have been deployed yet, so the address may be empty. For existence, either check for the code size or compare against the allPlugins array.

function computePluginAddress(IERC20Plugins stakingToken, IERC20 rewardsToken) external view returns (address);

Parameters

NameTypeDescription
stakingTokenIERC20PluginsAddress of the staking token.
rewardsTokenIERC20Address of the rewards token.

Returns

NameTypeDescription
<none>addressplugin Address of the plugin.

setDefaultPluginOwner

Set the default plugin owner.

function setDefaultPluginOwner(address pluginOwner) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
pluginOwneraddressAddress that will own the plugin (controls start/stop farming & rescue).

deployFarmingPluginWithDefaultOwner

Deploy a new farming plugin with the default plugin owner.

Access: only accounts with MANAGER_ROLE. Default plugin owner must be set.

function deployFarmingPluginWithDefaultOwner(
    IERC20Plugins stakingToken,
    IERC20 rewardsToken
)
    external
    onlyRole(MANAGER_ROLE)
    returns (address plugin);

Parameters

NameTypeDescription
stakingTokenIERC20PluginsERC-20 token users deposit (must support plugins).
rewardsTokenIERC20ERC-20 token distributed as rewards.

deployFarmingPlugin

Deploy a new farming plugin.

Access: only accounts with MANAGER_ROLE.

function deployFarmingPlugin(
    IERC20Plugins stakingToken,
    IERC20 rewardsToken,
    address pluginOwner
)
    external
    onlyRole(MANAGER_ROLE)
    returns (address plugin);

Parameters

NameTypeDescription
stakingTokenIERC20PluginsERC-20 token users deposit (must support plugins).
rewardsTokenIERC20ERC-20 token distributed as rewards.
pluginOwneraddressAddress that will own the plugin (controls start/stop farming & rescue).

_setDefaultPluginOwner

Set the default plugin owner.

function _setDefaultPluginOwner(address pluginOwner) internal;

Parameters

NameTypeDescription
pluginOwneraddressAddress that will own the plugin (controls start/stop farming & rescue).

_deployFarmingPlugin

Deploy a new farming plugin with a unique salt to avoid collisions.

function _deployFarmingPlugin(
    IERC20Plugins stakingToken,
    IERC20 rewardsToken,
    address pluginOwner
)
    internal
    returns (address plugin);

Parameters

NameTypeDescription
stakingTokenIERC20PluginsERC-20 token users deposit (must support plugins).
rewardsTokenIERC20ERC-20 token distributed as rewards.
pluginOwneraddressAddress that will own the plugin (controls start/stop farming & rescue).

Events

FarmingPluginCreated

Emitted when a new farming plugin is created.

event FarmingPluginCreated(
    address indexed stakingToken, address indexed rewardsToken, address indexed plugin, address pluginOwner
);

Parameters

NameTypeDescription
stakingTokenaddressERC-20 token users deposit (must support plugins).
rewardsTokenaddressERC-20 token distributed as rewards.
pluginaddressAddress of the new farming plugin.
pluginOwneraddressAddress that will own the plugin (controls start/stop farming & rescue).

DefaultPluginOwnerSet

Emitted when the default plugin owner is set.

event DefaultPluginOwnerSet(address indexed previousOwner, address indexed newOwner);

Parameters

NameTypeDescription
previousOwneraddressAddress that was the previous default plugin owner.
newOwneraddressAddress that will be the new default plugin owner.

Errors

ZeroAddress

Emitted when a zero address is used.

error ZeroAddress();

Contents

AutomaticWeightStrategy

Git Source

Inherits: WeightStrategy, AccessControlEnumerable, Multicall

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, Multicall

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

ZeroAddress

ERRORS ///

Error thrown when the address is zero.

error ZeroAddress();

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.

Errors

ZeroAddress

ERRORS ///

Thrown when the address is zero.

error ZeroAddress();

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

CoWSwapCloneCreated

EVENTS ///

Emitted when a new order is created.

event CoWSwapCloneCreated(
    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 proposalTimestamp;
    uint40 timestamp;
    uint8 retryCount;
    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;
    uint256 slippageLimit;
    uint256 weightDeviationLimit;
    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;
    address tokenSwapAdapter;
    uint8 retryLimit;
    uint40 stepDelay;
}

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;
}

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

ZeroAddress

ERRORS ///

Thrown when the asset address is zero.

error ZeroAddress();

AssetAlreadyEnabled

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, Rescuable

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;

_MIN_STEP_DELAY

Minimum time between steps in a rebalance in seconds.

uint40 private constant _MIN_STEP_DELAY = 1 minutes;

_MAX_STEP_DELAY

Maximum time between steps in a rebalance in seconds.

uint40 private constant _MAX_STEP_DELAY = 60 minutes;

_MAX_RETRY_COUNT

Maximum bound of retry count.

uint8 private constant _MAX_RETRY_COUNT = 10;

_MAX_SLIPPAGE_LIMIT

Maximum bound of slippage

uint256 private constant _MAX_SLIPPAGE_LIMIT = 0.5e18;

_MAX_WEIGHT_DEVIATION_LIMIT

Maximum bound of weight deviation

uint256 private constant _MAX_WEIGHT_DEVIATION_LIMIT = 0.5e18;

_bmStorage

STATE VARIABLES ///

Struct containing the BasketManagerUtils contract and other necessary data.

BasketManagerStorage private _bmStorage;

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

Parameters

NameTypeDescription
basketTokenaddressAddress of the basket token.

Returns

NameTypeDescription
<none>uint256Index of the basket token.

getAssetIndexInBasket

Returns the index of the given asset in the basket.

Reverts if the basket asset does not exist.

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

Parameters

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

Returns

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

basketTokenToBaseAssetIndex

Returns the index of the base asset in the given basket token

Reverts if the basket token does not exist

function basketTokenToBaseAssetIndex(address basketToken) public view returns (uint256);

Parameters

NameTypeDescription
basketTokenaddressAddress of the basket token

Returns

NameTypeDescription
<none>uint256Index of the base asset in the basket token's assets array

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 and target weights proposed for rebalance - basketMask: Bitmask representing baskets currently being rebalanced - epoch: Epoch of the rebalance - timestamp: Timestamp of the last action - retryCount: Number of retries for the current rebalance epoch - 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.

slippageLimit

Returns the slippage limit for token swaps denominated in 1e18.

function slippageLimit() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Maximum slippage.

weightDeviationLimit

Returns the weight deviation limit for token swaps denominated in 1e18.

function weightDeviationLimit() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Maximum weight deviation.

assetRegistry

Returns the address of the asset registry.

function assetRegistry() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the asset registry.

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.

retryLimit

Returns the maximum retry limit for the rebalance process.

function retryLimit() external view returns (uint8);

Returns

NameTypeDescription
<none>uint8Retry limit.

stepDelay

Returns the step delay for the rebalance process.

The step delay defines the minimum time interval, in seconds, required between consecutive steps in a rebalance. This ensures sufficient time for external trades or other operations to settle before proceeding.

function stepDelay() external view returns (uint40);

Returns

NameTypeDescription
<none>uint40Step delay duration in seconds.

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.

collectedSwapFees

Returns the collected swap fees for the given asset.

function collectedSwapFees(address asset) external view returns (uint256);

Parameters

NameTypeDescription
assetaddressAddress of the asset.

Returns

NameTypeDescription
<none>uint256Collected swap fees.

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,
    address[][] calldata basketAssets_
)
    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.
basketAssets_address[][]

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,
    address[][] calldata basketAssets_
)
    external
    nonReentrant
    whenNotPaused;

Parameters

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

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.

This function can only be called by basket tokens.

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.

setStepDelay

Updates the step delay for the rebalance process.

The step delay defines the minimum time interval, in seconds, required between consecutive steps in a rebalance. This ensures sufficient time for external trades or other operations to settle before proceeding.

function setStepDelay(uint40 stepDelay_) external onlyRole(_TIMELOCK_ROLE);

Parameters

NameTypeDescription
stepDelay_uint40The new step delay duration in seconds.

setRetryLimit

Sets the retry limit for future rebalances.

function setRetryLimit(uint8 retryLimit_) external onlyRole(_TIMELOCK_ROLE);

Parameters

NameTypeDescription
retryLimit_uint8New retry limit.

setSlippageLimit

Sets the slippage multiplier for token swaps.

function setSlippageLimit(uint256 slippageLimit_) external onlyRole(_TIMELOCK_ROLE);

Parameters

NameTypeDescription
slippageLimit_uint256New slippage limit.

setWeightDeviation

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

function setWeightDeviation(uint256 weightDeviationLimit_) external onlyRole(_TIMELOCK_ROLE);

Parameters

NameTypeDescription
weightDeviationLimit_uint256New weight deviation limit.

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.

_revertIfCurrentlyRebalancing

Reverts if a rebalance is currently in progress.

function _revertIfCurrentlyRebalancing() private view;

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

execute

Allows the timelock to execute an arbitrary function call on a target contract.

Can only be called by addresses with the timelock role. Reverts if the execution fails. Reverts if the target of the call is an asset that is active in the asset registry.

function execute(
    address target,
    bytes calldata data,
    uint256 value
)
    external
    payable
    onlyRole(_TIMELOCK_ROLE)
    returns (bytes memory);

Parameters

NameTypeDescription
targetaddressThe address of the target contract.
databytesThe calldata to send to the target contract.
valueuint256The amount of Ether (in wei) to send with the call.

Returns

NameTypeDescription
<none>bytesresult The data returned from the function call.

rescue

Allows the admin to rescue tokens mistakenly sent to the contract.

Can only be called by the admin. This function is intended for use in case of accidental token transfers into the contract. It will revert if the token is part of the enabled asset universe.

function rescue(IERC20 token, address to, uint256 balance) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
tokenIERC20The ERC20 token to rescue, or address(0) for ETH.
toaddressThe recipient address of the rescued tokens.
balanceuint256The amount of tokens to rescue. If set to 0, the entire balance will be rescued.

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, ExternalTrade[] externalTrades);

StepDelaySet

Emitted when the step delay is set.

event StepDelaySet(uint40 oldDelay, uint40 newDelay);

RetryLimitSet

Emitted when the retry limit is set.

event RetryLimitSet(uint8 oldLimit, uint8 newLimit);

SlippageLimitSet

Emitted when the max slippage is set.

event SlippageLimitSet(uint256 oldSlippage, uint256 newSlippage);

WeightDeviationLimitSet

Emitted when the max weight deviation is set

event WeightDeviationLimitSet(uint256 oldDeviation, uint256 newDeviation);

Errors

ZeroAddress

ERRORS ///

Thrown when the address is zero.

error ZeroAddress();

TokenSwapNotProposed

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

Thrown when attempting to update the bitFlag to the same value.

error BitFlagMustBeDifferent();

BitFlagMustIncludeCurrent

Thrown when attempting to update the bitFlag without including the current bitFlag.

error BitFlagMustIncludeCurrent();

BitFlagUnsupportedByStrategy

Thrown when attempting to update the bitFlag to a value not supported by the strategy.

error BitFlagUnsupportedByStrategy();

BasketIdAlreadyExists

Thrown when attempting to create a basket with an ID that already exists.

error BasketIdAlreadyExists();

AssetExistsInUniverse

Thrown when attempting to rescue an asset to a basket that already exists in the asset universe.

error AssetExistsInUniverse();

ExecutionFailed

Thrown when the low-level call in the execute function fails.

This error indicates that the target contract rejected the call or execution failed unexpectedly.

error ExecutionFailed();

InvalidStepDelay

Thrown when attempting to set an invalid step delay outside the bounds of _MIN_STEP_DELAY and _MAX_STEP_DELAY.

error InvalidStepDelay();

InvalidRetryCount

Thrown when attempting to set an invalid retry limit outside the bounds of 0 and _MAX_RETRY_COUNT.

error InvalidRetryCount();

InvalidSlippageLimit

Thrown when attempting to set a slippage limit greater than _MAX_SLIPPAGE_LIMIT.

error InvalidSlippageLimit();

InvalidWeightDeviationLimit

Thrown when attempting to set a weight deviation greater than _MAX_WEIGHT_DEVIATION_LIMIT.

error InvalidWeightDeviationLimit();

EmptyExternalTrades

Thrown when attempting to execute a token swap with empty external trades array

error EmptyExternalTrades();

BasketToken

Git Source

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

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

Considerations for Integrators: When users call requestDeposit or requestRedeem, the system ensures that the controller does not have any pending or claimable deposits or redeems from the controller's lastDepositRequestId. This behavior allows for a potential griefing attack: an attacker can call requestDeposit or requestRedeem with a minimal dust amount and specify the target controller address. As a result, the target controller would then be unable to make legitimate requestDeposit or requestRedeem requests until they first claim the pending request. RECOMMENDATION FOR INTEGRATORS: When integrating BasketToken into other contracts, always check for any pending or claimable tokens before requesting a deposit or redeem. This ensures that any pending deposits or redeems are resolved, preventing such griefing attacks.

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;

_NAME_PREFIX

string private constant _NAME_PREFIX = "Cove ";

_SYMBOL_PREFIX

string private constant _SYMBOL_PREFIX = "cove";

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.

getAssets

Returns all assets that are eligible to be included in this basket based on the bitFlag

*This returns the complete list of eligible assets from the AssetRegistry, filtered by this basket's bitFlag. The list includes all assets that could potentially be part of the basket, regardless of:

  • Their current balance in the basket
  • Their current target weight
  • Whether they are paused*
function getAssets() public view returns (address[] memory);

Returns

NameTypeDescription
<none>address[]Array of asset token addresses that are eligible for this basket

requestDeposit

ERC7540 LOGIC ///

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

Reverts on 0 assets or if the caller is not the owner or operator of the assets being deposited.

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

Prepares the basket token for rebalancing by processing pending deposits and redemptions.

*This function:

  • Verifies previous deposit/redeem requests were fulfilled
  • Advances deposit/redeem epochs if there are pending requests
  • Harvests management fees
  • Can only be called by the basket manager
  • Called at the start of rebalancing regardless of pending requests
  • Does not advance epochs if there are no pending requests*
function prepareForRebalance(
    uint16 feeBps,
    address feeCollector
)
    external
    returns (uint256 pendingDeposits, uint256 pendingShares);

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 base assets pending deposit.
pendingSharesuint256The 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

Retrieves the total amount of assets currently pending deposit.

Once a rebalance is proposed, any pending deposits are processed and this function will return the pending deposits of the next epoch.

function totalPendingDeposits() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256The total pending deposit amount.

totalPendingRedemptions

Returns the total number of shares pending redemption.

Once a rebalance is proposed, any pending redemptions are processed and this function will return the pending redemptions of the next epoch.

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.

claimFallbackShares

FALLBACK REDEEM LOGIC ///

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.

claimFallbackAssets

Claims assets given for a previous deposit request in the event a deposit fulfillment for a given epoch fails.

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

Parameters

NameTypeDescription
receiveraddressThe address to receive the assets.
controlleraddressThe address of the controller of the deposit request.

Returns

NameTypeDescription
assetsuint256The amount of assets 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.

claimableFallbackAssets

Returns the amount of assets claimable for a given user in the event of a failed deposit fulfillment.

function claimableFallbackAssets(address controller) public view returns (uint256 assets);

Parameters

NameTypeDescription
controlleraddressThe address of the controller.

Returns

NameTypeDescription
assetsuint256The amount of assets claimable by the controller.

proRataRedeem

Synchronously redeems basket shares for underlying assets at current proportions.

Bypasses rebalance process, transferring assets immediately. Requires basket to be out of rebalance cycle. Can be used to exit baskets with paused assets. See BasketManager-proRataRedeem and {AssetRegistry-setAssetStatus}.

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

Harvests management fees owed to the fee collector.

function harvestManagementFee() external;

_harvestManagementFee

Internal function to harvest management fees. Updates the timestamp of the last management fee harvest if a non zero fee is collected. Mints the fee to the fee collector and notifies the basket manager.

function _harvestManagementFee(uint16 feeBps, address feeCollector) internal;

Parameters

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

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

fallbackRedeemTriggered

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

function fallbackRedeemTriggered(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.

fallbackDepositTriggered

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

function fallbackDepositTriggered(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.

getDepositRequest

Returns the deposit request data for a given requestId without the internal mapping.

function getDepositRequest(uint256 requestId) external view returns (DepositRequestView memory);

Parameters

NameTypeDescription
requestIduint256The id of the deposit request.

Returns

NameTypeDescription
<none>DepositRequestViewA DepositRequestView struct containing the deposit request data.

getRedeemRequest

Returns the redeem request data for a given requestId without the internal mapping.

function getRedeemRequest(uint256 requestId) external view returns (RedeemRequestView memory);

Parameters

NameTypeDescription
requestIduint256The id of the redeem request.

Returns

NameTypeDescription
<none>RedeemRequestViewA RedeemRequestView struct containing the redeem request data.

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 return 18 decimals. See IERC20Metadata-decimals.

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

permit2

External wrapper around Permit2Lib's permit2 function to handle ERC20 permit signatures.

Supports both Permit2 and ERC20Permit (ERC-2612) signatures. Will try ERC-2612 first, then fall back to Permit2 if the token doesn't support ERC-2612 or if the permit call fails.

function permit2(
    IERC20 token,
    address owner,
    address spender,
    uint256 value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
)
    external;

Parameters

NameTypeDescription
tokenIERC20The token to permit
owneraddressThe owner of the tokens
spenderaddressThe spender to approve
valueuint256The amount to approve
deadlineuint256The deadline for the permit
vuint8The v component of the signature
rbytes32The r component of the signature
sbytes32The s component of the signature

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.

DepositFallbackTriggered

Emitted when a deposit request is triggered in fallback mode.

event DepositFallbackTriggered(uint256 indexed requestId);

Parameters

NameTypeDescription
requestIduint256The unique identifier of the deposit request.

RedeemFallbackTriggered

Emitted when a redemption request is triggered in fallback mode.

event RedeemFallbackTriggered(uint256 indexed requestId);

Parameters

NameTypeDescription
requestIduint256The unique identifier of the redemption request.

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.

DepositRequestQueued

Emitted when a deposit request is queued and awaiting fulfillment.

event DepositRequestQueued(uint256 depositRequestId, uint256 pendingDeposits);

Parameters

NameTypeDescription
depositRequestIduint256The unique identifier of the deposit request.
pendingDepositsuint256The total amount of assets pending deposit.

RedeemRequestQueued

Emitted when a redeem request is queued and awaiting fulfillment.

event RedeemRequestQueued(uint256 redeemRequestId, uint256 pendingShares);

Parameters

NameTypeDescription
redeemRequestIduint256The unique identifier of the redeem request.
pendingSharesuint256The total amount of shares pending redemption.

Errors

ZeroAddress

ERRORS ///

Thrown when the asset address is zero.

error ZeroAddress();

ZeroAmount

Thrown when the amount is zero.

error ZeroAmount();

ZeroPendingDeposits

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

ZeroClaimableFallbackAssets

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

error ZeroClaimableFallbackAssets();

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

NotFeeCollector

Thrown when an address other than the feeCollector attempts to harvest management fees.

error NotFeeCollector();

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

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;
    bool fallbackTriggered;
}

DepositRequestView

Typed tuple for externally viewing DepositRequestStruct without the mapping.

struct DepositRequestView {
    uint256 totalDepositAssets;
    uint256 fulfilledShares;
    bool fallbackTriggered;
}

RedeemRequestStruct

Struct representing a redeem request.

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

RedeemRequestView

Typed tuple for externally viewing RedeemRequestStruct without the mapping.

struct RedeemRequestView {
    uint256 totalRedeemShares;
    uint256 fulfilledAssets;
    bool fallbackTriggered;
}

FeeCollector

Git Source

Inherits: AccessControlEnumerable, Rescuable

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

_claimSponsorFee

Internal function to claim the sponsor fee for a given basket token. Will immediately redeem the shares through a proRataRedeem.

function _claimSponsorFee(address basketToken, address sponsor) internal;

Parameters

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

rescue

Rescue ERC20 tokens or ETH from the contract. Reverts if the balance trying to rescue exceeds the available balance minus claimable fees.

function rescue(IERC20 token, address to, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
tokenIERC20address of the token to rescue. Use zero address for ETH.
toaddressaddress to send the rescued tokens to
amountuint256amount of tokens to rescue

_checkIfBasketToken

Internal function to check if a given address is a basket token

function _checkIfBasketToken(address token) internal view;

Parameters

NameTypeDescription
tokenaddressThe address to check

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

ZeroAddress

ERRORS ///

Thrown when the address is zero.

error ZeroAddress();

SponsorSplitTooHigh

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

InsufficientFundsToRescue

Thrown funds attempted to be rescued exceed the available balance.

error InsufficientFundsToRescue();

Rescuable

Git Source

Allows the inheriting contract to rescue ERC20 tokens that are sent to it by mistake.

Functions

_rescue

Rescue any ERC20 tokens that are stuck in this contract. The inheriting contract that calls this function should specify required access controls

function _rescue(IERC20 token, address to, uint256 balance) internal;

Parameters

NameTypeDescription
tokenIERC20address of the ERC20 token to rescue. Use zero address for ETH
toaddressaddress to send the tokens to
balanceuint256amount of tokens to rescue. Use zero to rescue all

Errors

ZeroEthTransfer

Error for when an ETH transfer of zero is attempted.

error ZeroEthTransfer();

EthTransferFailed

Error for when an ETH transfer fails.

error EthTransferFailed();

ZeroTokenTransfer

Error for when a token transfer of zero is attempted.

error ZeroTokenTransfer();