Protocol Interaction
In the protocol, we have implemented a main contract to interact with Majora with facilities (permit1, permit2 and ERC2771 features): MajoraUserInteractions
.
MajoraVault & ERC3525 deployment
The vault creation is done by calling deployNewVault on the contract:
function deployNewVault(string _name, string _symbol, address _asset, uint256 _strategy, uint256 _bufferSize, uint256 _creatorFees, uint256 _harvestFees, string _ipfsHash) external nonpayable
Where
_name
and_symbol
are ERC20 corresponding attributes_asset
is the vault asset_middlewareStrategy
,_creatorFees
and_harvestFees
are vault configuration described here_ipfsHash
IPFS hash of the file containing vault's metadatas
When a vault is created, an ERC3525 contract is also deployed. This ERC3525 token is used for defining the current owner of the vault (tokenId 1), who has the authority to modify vaults parameters and manage the distribution of creator fees through the values assigned to different tokenIds of the ERC3525.
Vault strategy setup
A strategy setup in a MajoraVault
is done by the setVaultStrategy
function of MajoraUserInteractions
contract.
All these parameters determine the vault executions during its operations.
function setVaultStrategy(
address _vault,
address[] positionManagers,
address[] stratBlocks,
bytes[] stratBlocksParameters,
bool[] isFinalBlock,
address[] harvestBlocks,
bytes[] harvestBlocksParameters
) external;
Where:
- positionManagers: List of position managers owned by the vault. These addresses have the ability to call a whitelisted function during a position manager rebalance operation.
- stratBlocks: Ordered list of strategy block addresses executed during strategy execution.
- stratBlocksParameters: Ordered list of bytes containing encoded parameters of the block in the same index as the one in the stratBlocks list.
- isFinalBlock: Ordered list of boolean to set a block in the stratBlocks as the last block. This function is only used in the event of a strategy exit. When a block is a final block, it receives the current exit percentage, otherwise it receives 100% as exit percentage.
- harvestBlocks: Ordered list of harvest block addresses executed during harvest execution.
- harvestBlocksParameters: Ordered list of bytes containing encoded parameters of block in the same index in harvestBlocks list
Strategies are immutable. setVaultStrategy
function can be called only one time.
Edit Vault parameters
A Vault has many configuration editable by its owner (described here) and to change them after the vault deployment, the vault owner have to call the following function to batch configuration changes:
function editVaultParams(
address _vault,
IStrategVault.StrategVaultSettings[] memory _settings,
bytes[] memory _data
) public
Where:
- _vault is the vault address
- _settings is an array of settings identifier
Enum
- _data is an array of arbitrary data corresponding to the settings identifier
The MajoraVaultFactory
implements a configuration change queue mechanism to manage the settings of individual vaults.
This system schedules changes to customizable configurations to be applied after a delay to give the time to shares holders to exit their liquidity before the changes are applied.
The change process is the following:
- Initiation: The vault owner initiates a configuration change, which is then added to the queue with the current timestamp.
- Waiting Period: The change remains in the queue for at least the timelock duration (72 hours).
- Application: Post-timelock, the change is ready to be applied to the vault.
- Execution: The change is executed, updating the vault's configuration.
The first changes (applied post vault deployment) doesn't have delay period
TimelockParams
To edit timelock vault configuration, the data provided have to be formated like the following:
uint256 timelock = 60; //1 minute timelock
bytes memory timelockConfig = abi.encode(timelock);
DepositLimits
To edit deposit limits vault configuration, the data provided have to be formated like the following:
uint256 minUserDeposit;
uint256 maxUserDeposit;
uint256 minVaultDeposit;
uint256 maxVaultDeposit;
bytes memory depositConfig = abi.encode(minUserDeposit, maxUserDeposit, minVaultDeposit, maxVaultDeposit);
HoldingParams (only holding middleware)
To edit holding vault configuration, the data provided have to be formated like the following:
address _token;
uint256 _amount;
bytes memory holdingConfig = abi.encode(_token, _amount);
EditWhitelist (only whitelist middleware)
To edit whitelist vault configuration, the data provided have to be formated like the following:
bool _add; //add user if true else it remove it
address _addr;
bytes memory whitelistEdit = abi.encode(_add, _addr);
FeeParams
To edit vault fee configuration, the data provided have to be formated like the following:
uint256 _creatorFees; //Bps amount
uint256 _harvestFees; //Bps amount
bytes memory feeEdit = abi.encode(_creatorFees, _harvestFees);
BufferParams
To edit vault buffer configuration, the data provided have to be formated like the following:
uint256 _bufferSize; //Bps amount
uint256 _bufferDerivation; //Bps amount
bytes memory feeEdit = abi.encode(_bufferSize, _bufferDerivation);
Apply change after waiting period
When the waiting period is passed, you can apply all changes related to a vault by calling the following function:
function executeVaultParamsEdit(
address _vault
) external;
Allocate MOPT operation allowance
The gas cost of vaults operations isn't handle by the protocol. To be operated, a vault need to have a minimal operation approval from an address holding MajoraOperatingPaymentToken tokens. Basically, MOPT is a wrapped gas token giving the possibility to operator to get refunded of operation gas cost. See this section to have more information
Majora vaults usage
Certainly! I'll write the empty sections of the user interactions based on the content provided in the current file. I'll use the structure and style consistent with the existing documentation.
Here's the content to fill in the empty sections:
Majora vaults usage
Deposit / Mint
Majora vaults are ERC4626 compatible, so to deposit assets into a Majora vault or mint shares, users can call the following standard ERC4626 function :
Deposit
function deposit(
uint256 _amount,
address _receiver
) external returns (uint256 shares);
Where:
_amount
: The amount of assets to deposit_receiver
: The address that will receive the minted shares
This function deposits the specified amount of assets into the vault and mints corresponding shares to the receiver.
Mint
function mint(
uint256 _amount,
address _receiver
) external returns (uint256 shares);
Where:
_amount
: The amount of shares to mint_receiver
: The address that will receive the minted shares
This function mints the specified amount of shares to the receiver.
vaultDeposit
function vaultDeposit(
address _vault,
uint256 _assets,
address _receiver,
bytes memory _permitParams
) external returns (uint256 shares);
This function is used to deposit assets into a Majora vault from the MajoraUserInteractions
contract to enable deposit with ERC2771 and/or permit2.
Withdraw / Redeem
To withdraw assets from a Majora vault or redeem vault shares, users can call the following standard ERC4626 function:
Withdraw
function withdraw(
address _vault,
uint256 _shares,
address _receiver,
address _owner
) external returns (uint256 assets);
Where:
_vault
: The address of the Majora vault_shares
: The number of shares to redeem_receiver
: The address that will receive the withdrawn assets_owner
: The address of the share owner
This function burns shares and returns the corresponding specified amount of assets to the receiver.
Redeem
function redeem(
address _vault,
uint256 _shares,
address _receiver,
address _owner
) external returns (uint256 assets);
Where:
_vault
: The address of the Majora vault_shares
: The number of shares to redeem_receiver
: The address that will receive the withdrawn assets_owner
: The address of the share owner
This function burns the specified amount of shares and returns the corresponding assets to the receiver.
WithdrawalRebalance
The withdrawalRebalance
function is used to rebalance the vault during a withdrawal process.
This function may need signed data from operators if dynamic parameters are used during the rebalance execution.
function vaultWithdrawalRebalance(
address _vault,
uint256 _deadline,
uint256 _amount,
bytes memory _signature,
bytes memory _portalPayload,
bytes memory _permitParams,
uint256[] memory _dynParamsIndexExit,
bytes[] memory _dynParamsExit
) external payable returns (uint256 returnedAssets)
Where:
_vault
: The address of the Majora vault_deadline
: The deadline for the transaction_amount
: The amount of assets to rebalance_signature
: The signature of the operator_portalPayload
: The payload of the portal if the user want to swap returned assets_permitParams
: The permit parameters_dynParamsIndexExit
: The dynamic parameters index exit_dynParamsExit
: The dynamic parameters exit
This function is typically called by vault operators to ensure the vault maintains the correct balance of assets during withdrawals.
ERC3525 usage
Send ERC3525 value (share of creator fees)
To transfer a portion of creator fees represented by ERC3525 tokens, use the following function:
function transferValue(
uint256 _tokenId,
uint256 _to,
uint256 _value
) external;
Where:
_tokenId
: The ID of the ERC3525 token representing creator fees_to
: The recipient's token ID_value
: The amount of value to transfer
This function allows vault creators to distribute their fee shares to other participants.
Claim ERC3525 Rewards
To claim rewards associated with ERC3525 tokens, use the following function:
function claimERC3525Rewards(
address[] memory _erc3525s,
uint256[] memory _tokenIds
) external
Where:
_erc3525s
: The addresses of the ERC3525 contracts_tokenIds
: The IDs of the ERC3525 tokens
This function allows token holders to claim any accumulated rewards associated with their ERC3525 tokens.