Skip to main content

R25 Contract Integration Guide

1. Understand the Two Operating Models​

Vaults operate in either synchronous or asynchronous mode.

Synchronous Vault:

User approval -> Deposit/Redeem -> Transaction confirmation -> Assets or Shares are delivered immediately

Asynchronous Vault:

User submits a request
-> Pending (waiting for keeper processing)
-> Settled (the keeper settles the request and the Assets or Shares have been delivered)

For an asynchronous Vault:

  • requestDeposit / requestRedeem submit requests.
  • settleDeposit / settleRedeem are called by a keeper to settle requests.
  • There is no separate user claim step. Claim-style entry points such as deposit / redeem revert.
  • The current implementation has no Claimable / Claimed states and no standalone RequestManager.

An asynchronous request is not finally priced when it is submitted. The final amount of Shares or Assets is determined by the keeper settlement result.

2. Common Parameters​

ParameterDescription
assetsAmount of the underlying Asset, such as USDC, expressed using the Asset Token's decimals
sharesAmount of Vault Shares, expressed using the ShareToken's decimals
receiverAddress that ultimately receives Shares or underlying Assets in a synchronous flow
ownerAddress that provides the Assets or Shares
controllerController of an asynchronous request, used for request queries and business attribution
inviteCodeOptional referral or channel code used only for attribution
requestIdAsynchronous request ID; deposit and redeem request IDs increment independently

The Asset Token and ShareToken may use different decimals. Integrators must read them separately.

3. Prerequisites​

Deposits​

  1. The user has sufficient Assets.
  2. If the Vault has a deposit window, deposits are currently open.
  3. If the Vault has amount limits, the amount satisfies the minimum, maximum, and total-cap limits.
  4. If the Vault has a whitelist, the whitelist check passes.
  5. The user has approved the Vault to spend the Assets.
  6. The current Vault price is valid.

Approval:

asset.approve(vault, assets);

The spender must be the Vault address.

Whitelist target:

ScenarioAddress that must be whitelisted
A user wallet calls a synchronous Vault directlyThe user wallet, i.e. msg.sender
A project contract calls a synchronous Vault on the user's behalfThe project contract, i.e. msg.sender
Asynchronous requestDepositThe Asset provider, i.e. owner

Redemptions​

  1. The user has sufficient Shares.
  2. If the Vault has a redemption window, redemptions are currently open.
  3. If the Vault has a lock-up period, the product is no longer locked.
  4. If the Vault has redemption limits, the amount satisfies those limits.
  5. The current Vault price is valid.

Redemptions do not check the deposit whitelist.

A user redeeming their own Shares does not need an additional approval. If a project contract calls a synchronous redemption on the user's behalf, the user must approve the project contract:

share.approve(projectContract, shares);

Delegated permissions in asynchronous flows:

OperationAuthorized caller
Submit a deposit or redeem requestThe owner, or an operator authorized by the owner
Cancel a requestThe current implementation allows the owner, or an operator authorized by the owner
Settle a requestA keeper, i.e. an address with VAULT_KEEPER_ROLE

Operator authorization:

vault.setOperator(projectContract, true);

Event Addresses​

Relevant events for a Vault transaction may be emitted by three contracts:

ContractHow to obtain the addressMain events
Asset Tokenvault.asset()Approval, Asset Transfer
ShareTokenvault.share()Share Approval, Share Transfer
CoreVaultSync / CoreVaultAsyncCurrent Vault addressDeposit, Withdraw, DepositRequest, RedeemRequest, DepositRequestSettled, RedeemRequestSettled, DepositRequestCancelled, RedeemRequestCancelled, ReferralRecorded, OperatorSet

The current implementation has no standalone RequestManager and no vault.requestManager(). Integrators must not monitor only the Vault address, or they will miss token transfer events emitted by the Asset Token and ShareToken.

4. Synchronous Deposits​

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

Version with a referral code:

function deposit(
uint256 assets,
address receiver,
string calldata inviteCode
) external returns (uint256 shares);
ParameterDescription
assetsAmount of Assets deposited by the user
receiverAddress receiving the Shares
inviteCodeOptional referral or channel code
Returned sharesActual number of Shares received by receiver

Call sequence:

  1. Call previewDeposit(assets) to estimate the number of Shares.
  2. The user calls asset.approve(vault, assets).
  3. Call deposit(assets, receiver).
  4. Monitor the Deposit event.
  5. After receiving Deposit, mark the deposit order as completed.

Events in the flow:

EventEmitting contractMeaning
Asset ApprovalAsset TokenThe user has approved the Vault to spend Assets; this does not mean the deposit is complete
Asset TransferAsset TokenAssets have moved from the user to the Vault custody address
Share Transfer(0, receiver, shares)ShareTokenShares have been minted to receiver
Vault DepositCoreVaultSyncThe synchronous deposit is complete
ReferralRecordedCoreVaultSyncThe referral code has been recorded for attribution only

4.2 Optional Interface: User Specifies the Target Number of Shares​

function mint(
uint256 shares,
address receiver
) external returns (uint256 assets);
ParameterDescription
sharesNumber of Shares the user wants to receive
receiverAddress receiving the Shares
Returned assetsActual amount of Assets paid by the user

Before calling, use previewMint(shares) to estimate the required Asset amount.

For ordinary user deposits, deposit is recommended.

5. Synchronous Redemptions​

function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
ParameterDescription
sharesNumber of Shares used in this redemption
receiverAddress receiving the Assets
ownerOwner of the Shares
Returned assetsActual amount of Assets received by receiver

Call sequence:

  1. Call previewRedeem(shares) to estimate the Asset amount.
  2. No Share approval is required when the user calls for their own Shares.
  3. For a delegated call, the owner first approves the project contract to use the Shares.
  4. Call redeem(shares, receiver, owner).
  5. Monitor the Withdraw event.
  6. After receiving Withdraw, mark the redemption order as completed.

Events in the flow:

EventEmitting contractMeaning
Share Transfer(owner, 0, sharesToBurn)ShareTokenThe net Shares used for redemption have been burned after deducting any Share-denominated redemption fee
Share Transfer(owner, feeReceiver, feeShares)ShareTokenIf a Share-denominated redemption fee applies, the fee Shares have been transferred
Asset Transfer(..., receiver, assets)Asset TokenAssets have been sent to receiver
Vault WithdrawCoreVaultSyncThe synchronous redemption is complete

When a Share-denominated redemption fee is enabled, the input shares is split into feeShares and sharesToBurn. The order result must be determined from the Vault's Withdraw event, not inferred from a single Share Transfer event.

5.2 Optional Interface: User Specifies the Target Asset Amount​

function withdraw(
uint256 assets,
address receiver,
address owner
) external returns (uint256 shares);
ParameterDescription
assetsAmount of Assets the user wants to receive
receiverAddress receiving the Assets
ownerOwner of the Shares
Returned sharesActual number of Shares used

Before calling, use previewWithdraw(assets) to estimate the required number of Shares.

For ordinary user redemptions, redeem is recommended.

6. Asynchronous Deposits​

6.1 Submit a Request​

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

Version with a referral code:

function requestDeposit(
uint256 assets,
address controller,
address owner,
string calldata inviteCode
) external returns (uint256 requestId);
ParameterDescription
assetsAmount of Assets locked from owner
controllerController of the request
ownerUser providing the Assets and the address checked against the whitelist
inviteCodeOptional referral or channel code
Returned requestIdDeposit request ID

For a user acting directly, the usual values are:

controller = user address
owner = user address

Call sequence:

  1. The user calls asset.approve(vault, assets).
  2. Call requestDeposit(assets, controller, owner).
  3. Monitor DepositRequest, create the order, and set its status to Pending.
  4. Wait for a keeper to call settleDeposit(requestId) or batchSettleDeposits(requestIds).
  5. Monitor DepositRequestSettled and Deposit.
  6. After receiving the settlement event, set the deposit order status to Settled.

Before a project contract submits a request on behalf of owner, the owner must authorize it:

vault.setOperator(projectContract, true);

6.2 Keeper Settlement of Shares​

function settleDeposit(
uint256 requestId
) external returns (uint256 shares);

Batch version:

function batchSettleDeposits(
uint256[] calldata requestIds
) external returns (uint256 shares);
ParameterDescription
requestIdID of the deposit request to settle
Returned sharesActual number of Shares minted to owner

In the current implementation, the keeper mints Shares directly to owner during settlement. The user neither needs nor is able to call deposit(assets, receiver, controller) afterward to claim them.

The following asynchronous Vault methods do not represent claimable amounts:

vault.maxDeposit(controller);              // Returns 0
vault.claimableDepositRequest(id, user); // Returns 0

6.3 Business Events​

StageEventEmitting contractBusiness meaningOrder status
Request submissionAsset Transfer(owner, escrow, assets)Asset TokenAssets have moved from owner to custody and are lockedPending
Request submissionDepositRequestCoreVaultAsyncAssets are locked and the deposit request has been submittedPending
Keeper settlementDepositRequestSettledCoreVaultAsyncShares have been calculated using the current NAV and settledSettled
Keeper settlementShare Transfer(0, owner, shares)ShareTokenShares have been minted to ownerSettled
Keeper settlementVault DepositCoreVaultAsyncThe asynchronous deposit settlement is completeSettled

7. Asynchronous Redemptions​

7.1 Submit a Request​

function requestRedeem(
uint256 shares,
address controller,
address owner
) external returns (uint256 requestId);
ParameterDescription
sharesNumber of Shares locked from owner
controllerController of the request
ownerOwner of the Shares
Returned requestIdRedeem request ID

For a user acting directly, the usual values are:

controller = user address
owner = user address

Call sequence:

  1. Call requestRedeem(shares, controller, owner).
  2. Monitor RedeemRequest, create the order, and set its status to Pending.
  3. Wait for a keeper to call settleRedeem(requestId) or batchSettleRedeems(requestIds).
  4. Monitor RedeemRequestSettled and Withdraw.
  5. After receiving the settlement event, set the redemption order status to Settled.

No additional Share approval is required when the user calls directly or an authorized operator calls on the user's behalf. Before a project contract calls on behalf of the user, the recommended authorization is:

vault.setOperator(projectContract, true);

7.2 Keeper Settlement of Assets​

function settleRedeem(
uint256 requestId
) external returns (uint256 assets);

Batch version:

function batchSettleRedeems(
uint256[] calldata requestIds
) external returns (uint256 assets);
ParameterDescription
requestIdID of the redeem request to settle
Returned assetsActual amount of Assets sent to owner

In the current implementation, the keeper sends Assets directly to owner during settlement. The user neither needs nor is able to call redeem(shares, receiver, controller) afterward to claim them.

The following asynchronous Vault methods do not represent claimable amounts:

vault.maxRedeem(controller);              // Returns 0
vault.claimableRedeemRequest(id, user); // Returns 0

7.3 Business Events​

StageEventEmitting contractBusiness meaningOrder status
Request submissionShare Transfer(owner, escrow, shares)ShareTokenShares are lockedPending
Request submissionRedeemRequestCoreVaultAsyncThe redeem request has been submittedPending
Keeper settlementRedeemRequestSettledCoreVaultAsyncAssets have been calculated using the current NAV and settledSettled
Keeper settlementShare Transfer(escrow, feeReceiver, feeShares)ShareTokenIf a Share-denominated redemption fee applies, the fee Shares have been transferredSettled
Keeper settlementShare Transfer(escrow, 0, sharesToBurn)ShareTokenThe net Shares have been burned after deducting the redemption feeSettled
Keeper settlementAsset Transfer(..., owner, assets)Asset TokenAssets have been sent to ownerSettled
Keeper settlementVault WithdrawCoreVaultAsyncThe asynchronous redemption settlement is completeSettled

The result of an asynchronous redemption must be determined from the RedeemRequestSettled and Withdraw events, not inferred from a single Share Transfer event.

8. Cancel an Asynchronous Request​

Cancel a deposit request:

function cancelDepositRequest(
uint256 requestId
) external returns (uint256 assets);

Cancel a redeem request:

function cancelRedeemRequest(
uint256 requestId
) external returns (uint256 shares);
ParameterDescription
requestIdID of the request to cancel
Returned assetsAssets refunded when a deposit request is cancelled
Returned sharesShares refunded when a redeem request is cancelled

Rules:

  • The current implementation allows the owner, or an operator authorized by the owner, to cancel.
  • Only a Pending request can be cancelled.
  • A Settled request cannot be cancelled.
  • Cancelling a deposit request returns the Assets to owner.
  • Cancelling a redeem request returns the Shares to owner.

Events:

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

event RedeemRequestCancelled(
uint256 indexed requestId,
address indexed controller,
address indexed owner,
uint256 shares
);

Refund transfer events:

  • Cancel deposit: the Asset Token emits Transfer(escrow, owner, assets).
  • Cancel redeem: the ShareToken emits Transfer(escrow, owner, shares).

After receiving DepositRequestCancelled or RedeemRequestCancelled, set the order status to Cancelled.

9. Main Event Parameters​

Deposit​

Emitted by CoreVaultSync or CoreVaultAsync.

event Deposit(
address indexed sender,
address indexed owner,
uint256 assets,
uint256 shares
);
ParameterDescription
senderThe actual caller for a synchronous deposit; the keeper for an asynchronous settlement
ownerThe Share receiver for a synchronous deposit; the request owner for an asynchronous settlement
assetsAsset amount associated with this deposit or settlement
sharesActual number of Shares received

Withdraw​

Emitted by CoreVaultSync or CoreVaultAsync.

event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
ParameterDescription
senderThe actual caller for a synchronous redemption; the keeper for an asynchronous settlement
receiverThe Asset receiver for a synchronous redemption; the request owner for an asynchronous settlement
ownerThe Share owner for a synchronous redemption; the request owner for an asynchronous settlement
assetsActual amount of Assets sent
sharesActual number of Shares used or locked

DepositRequest​

Emitted by CoreVaultAsync.

event DepositRequest(
address indexed controller,
address indexed owner,
uint256 indexed requestId,
address sender,
uint256 assets
);
ParameterDescription
controllerController of the request
ownerAsset provider
requestIdRequest ID
senderUser or project contract that actually submitted the transaction
assetsAmount of Assets locked for the deposit request

RedeemRequest​

Emitted by CoreVaultAsync.

event RedeemRequest(
address indexed controller,
address indexed owner,
uint256 indexed requestId,
address sender,
uint256 shares
);
ParameterDescription
controllerController of the request
ownerOwner of the Shares
requestIdRequest ID
senderUser or project contract that actually submitted the transaction
sharesNumber of Shares locked for the redeem request

DepositRequestSettled​

Emitted by CoreVaultAsync.

event DepositRequestSettled(
uint256 indexed requestId,
address indexed controller,
address indexed owner,
uint256 assets,
uint256 shares
);

This event means the deposit request has been settled and the Shares have been minted directly to owner.

RedeemRequestSettled​

Emitted by CoreVaultAsync.

event RedeemRequestSettled(
uint256 indexed requestId,
address indexed controller,
address indexed owner,
uint256 shares,
uint256 assets
);

This event means the redeem request has been settled and the Assets have been sent directly to owner.

Cancellation Events​

Emitted by CoreVaultAsync.

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

event RedeemRequestCancelled(
uint256 indexed requestId,
address indexed controller,
address indexed owner,
uint256 shares
);

Token and Authorization Events​

EventEmitting contractParameter meaning
Approval(owner, spender, value)Asset Token or ShareTokenowner authorizes spender to use value tokens
Transfer(from, to, value)Asset Token or ShareTokenvalue Assets or Shares move from from to to
ReferralRecorded(sender, referralCode)CoreVaultSync or CoreVaultAsyncsender used referralCode; attribution only
OperatorSet(controller, operator, approved)CoreVaultAsynccontroller grants or revokes delegated access for operator

10. Order Status Updates​

Business eventEmitting contractIntegrator order status
Synchronous DepositCoreVaultSyncCompleted
Synchronous WithdrawCoreVaultSyncCompleted
DepositRequest / RedeemRequestCoreVaultAsyncPending
DepositRequestSettled / RedeemRequestSettledCoreVaultAsyncSettled
DepositRequestCancelled / RedeemRequestCancelledCoreVaultAsyncCancelled

The recommended unique business key for an asynchronous order is:

(chainId, vault, requestType, requestId)

Use requestType to distinguish deposit from redeem, because deposit and redeem request IDs increment independently in this implementation.

11. Contract ABIs​

The following smart contract ABI (Application Binary Interface) JSON files are available for download:

ContractFileDownload
CoreVaultSyncCoreVaultSync.jsonDownload
CoreVaultAsyncCoreVaultAsync.jsonDownload
ProjectFeeTreasuryProjectFeeTreasury.jsonDownload