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;

_bmStorage

STATE VARIABLES ///

Struct containing the BasketManagerUtils contract and other necessary data.

BasketManagerStorage private _bmStorage;

isOrderValid

Mapping of order hashes to their validity status.

mapping(bytes32 => bool) public isOrderValid;

Functions

constructor

Initializes the contract with the given parameters.

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

Parameters

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

basketTokenToIndex

PUBLIC FUNCTIONS ///

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

Reverts if the basket token does not exist.

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

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.

numOfBasketTokens

Returns the number of basket tokens.

function numOfBasketTokens() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256Number of basket tokens.

basketTokens

Returns all basket token addresses.

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

Returns

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

basketIdToAddress

Returns the basket token address with the given basketId.

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

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

Parameters

NameTypeDescription
basketIdbytes32Basket ID.

basketBalanceOf

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

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

Parameters

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

Returns

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

rebalanceStatus

Returns the current rebalance status.

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

Returns

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

externalTradesHash

Returns the hash of the external trades stored during proposeTokenSwap

function externalTradesHash() external view returns (bytes32);

Returns

NameTypeDescription
<none>bytes32Hash of the external trades

eulerRouter

Returns the address of the basket token implementation.

function eulerRouter() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the basket token implementation.

feeCollector

Returns the address of the feeCollector contract.

function feeCollector() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the feeCollector.

managementFee

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

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

Parameters

NameTypeDescription
basketaddressAddress of the basket.

Returns

NameTypeDescription
<none>uint16Management fee.

swapFee

Returns the swap fee in BPS denominated in 1e4.

function swapFee() external view returns (uint16);

Returns

NameTypeDescription
<none>uint16Swap fee.

strategyRegistry

Returns the address of the strategy registry.

function strategyRegistry() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the strategy registry.

tokenSwapAdapter

Returns the address of the token swap adapter.

function tokenSwapAdapter() external view returns (address);

Returns

NameTypeDescription
<none>addressAddress of the token swap adapter.

retryCount

Returns the retry count for the current rebalance epoch.

function retryCount() external view returns (uint8);

Returns

NameTypeDescription
<none>uint8Retry count.

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.

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.

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.

collectSwapFee

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

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

Parameters

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

updateBitFlag

Updates the bitFlag for the given basket.

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

Parameters

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

pause

PAUSING FUNCTIONS ///

Pauses the contract. Callable by DEFAULT_ADMIN_ROLE or PAUSER_ROLE.

function pause() external;

unpause

Unpauses the contract. Only callable by DEFAULT_ADMIN_ROLE.

function unpause() external onlyRole(DEFAULT_ADMIN_ROLE);

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.

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

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

Errors

TokenSwapNotProposed

ERRORS ///

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

error TokenSwapNotProposed();

ExecuteTokenSwapFailed

Thrown when the call to TokenSwapAdapter.executeTokenSwap fails.

error ExecuteTokenSwapFailed();

InvalidHash

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

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

error InvalidHash();

ExternalTradesHashMismatch

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

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

error ExternalTradesHashMismatch();

MustWaitForRebalanceToComplete

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

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

error MustWaitForRebalanceToComplete();

Unauthorized

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

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

error Unauthorized();

InvalidManagementFee

Thrown when attempting to set an invalid management fee.

The management fee must not exceed _MAX_MANAGEMENT_FEE.

error InvalidManagementFee();

InvalidSwapFee

Thrown when attempting to set an invalid swap fee.

The swap fee must not exceed _MAX_SWAP_FEE.

error InvalidSwapFee();

BasketTokenNotFound

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

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

error BasketTokenNotFound();

BitFlagMustBeDifferent

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