Provisioner
Last updated
Last updated
Inherits: IProvisioner, Auth2Step, ReentrancyGuardTransient
Entry and exit point for {MultiDepositorVault}. Handles all deposits and redemptions Uses {IPriceAndFeeCalculator} to convert between tokens and vault units. Supports both sync and async deposits; only async redeems. Manages deposit caps, refund timeouts, and request replay protection. All assets must flow through this contract to enter or exit the vault. Sync deposits are processed instantly, but stay refundable for a period of time. Async requests can either be solved by authorized solvers, going through the vault, or directly by anyone willing to pay units (for deposits) or tokens (for redeems), pocketing the solver tip, always paid in tokens
The price and fee calculator contract
IPriceAndFeeCalculator public immutable PRICE_FEE_CALCULATOR;
The multi depositor vault contract
address public immutable MULTI_DEPOSITOR_VAULT;
Mapping of token to token details
mapping(IERC20 token => TokenDetails details) public tokensDetails;
Maximum total value of deposits in numeraire terms
uint256 public depositCap;
Time period in seconds during which sync deposits can be refunded
uint256 public depositRefundTimeout;
Mapping of active sync deposit hashes
True if a sync deposit is active with the hashed parameters
mapping(bytes32 syncDepositHash => bool exists) public syncDepositHashes;
Mapping of async deposit hash to its existence
True if deposit request exists, false if it was refunded or solved
mapping(bytes32 asyncDepositHash => bool exists) public asyncDepositHashes;
Mapping of async redeem hash to its existence
True if redeem request exists, false if it was refunded or solved
mapping(bytes32 asyncRedeemHash => bool exists) public asyncRedeemHashes;
Mapping of user address to timestamp until which their units are locked
mapping(address user => uint256 unitsLockedUntil) public userUnitsRefundableUntil;
Ensures the caller is not the vault
modifier anyoneButVault();
constructor(
IPriceAndFeeCalculator priceAndFeeCalculator,
address multiDepositorVault,
address owner_,
Authority authority_
) Auth2Step(owner_, authority_);
Deposit tokens directly into the vault
MUST revert if tokensIn is 0, minUnitsOut is 0, or sync deposits are disabled
function deposit(IERC20 token, uint256 tokensIn, uint256 minUnitsOut)
external
anyoneButVault
returns (uint256 unitsOut);
Parameters
token
IERC20
The token to deposit
tokensIn
uint256
The amount of tokens to deposit
minUnitsOut
uint256
The minimum amount of units expected
Returns
unitsOut
uint256
The amount of shares minted to the receiver
Mint exact amount of units by depositing required tokens
function mint(IERC20 token, uint256 unitsOut, uint256 maxTokensIn) external anyoneButVault returns (uint256 tokensIn);
Parameters
token
IERC20
The token to deposit
unitsOut
uint256
The exact amount of units to mint
maxTokensIn
uint256
Maximum amount of tokens willing to deposit
Returns
tokensIn
uint256
The amount of tokens used to mint the requested shares
Refund a deposit within the refund period
Only callable by authorized addresses
function refundDeposit(address sender, IERC20 token, uint256 tokenAmount, uint256 unitsAmount, uint256 refundableUntil)
external
requiresAuth;
Parameters
sender
address
The original depositor
token
IERC20
The deposited token
tokenAmount
uint256
The amount of tokens deposited
unitsAmount
uint256
The amount of units minted
refundableUntil
uint256
Timestamp until which refund is possible
Create a new deposit request to be solved by solvers
function requestDeposit(
IERC20 token,
uint256 tokensIn,
uint256 minUnitsOut,
uint256 solverTip,
uint256 deadline,
uint256 maxPriceAge,
bool isFixedPrice
) external anyoneButVault;
Parameters
token
IERC20
The token to deposit
tokensIn
uint256
The amount of tokens to deposit
minUnitsOut
uint256
The minimum amount of units expected
solverTip
uint256
The tip offered to the solver
deadline
uint256
Duration in seconds for which the request is valid
maxPriceAge
uint256
Maximum age of price data that solver can use
isFixedPrice
bool
Whether the request is a fixed price request
Create a new redeem request to be solved by solvers
function requestRedeem(
IERC20 token,
uint256 unitsIn,
uint256 minTokensOut,
uint256 solverTip,
uint256 deadline,
uint256 maxPriceAge,
bool isFixedPrice
) external anyoneButVault;
Parameters
token
IERC20
The token to receive
unitsIn
uint256
The amount of units to redeem
minTokensOut
uint256
The minimum amount of tokens expected
solverTip
uint256
The tip offered to the solver
deadline
uint256
Duration in seconds for which the request is valid
maxPriceAge
uint256
Maximum age of price data that solver can use
isFixedPrice
bool
Whether the request is a fixed price request
Refund an expired deposit or redeem request
Can only be called after request deadline has passed
function refundRequest(IERC20 token, Request calldata request) external nonReentrant;
Parameters
token
IERC20
The token involved in the request
request
Request
The request to refund
Solve multiple requests using vault's liquidity
Only callable by authorized addresses
function solveRequestsVault(IERC20 token, Request[] calldata requests) external requiresAuth nonReentrant;
Parameters
token
IERC20
The token for which to solve requests
requests
Request[]
Array of requests to solve
Solve multiple requests using solver's own liquidity
function solveRequestsDirect(IERC20 token, Request[] calldata requests) external nonReentrant;
Parameters
token
IERC20
The token for which to solve requests
requests
Request[]
Array of requests to solve
Update deposit parameters
function setDepositDetails(uint256 depositCap_, uint256 depositRefundTimeout_) external requiresAuth;
Parameters
depositCap_
uint256
New maximum total value that can be deposited
depositRefundTimeout_
uint256
New time window for deposit refunds
Update token parameters
function setTokenDetails(IERC20 token, TokenDetails calldata details) external requiresAuth;
Parameters
token
IERC20
The token to update
details
TokenDetails
Removes token from provisioner
function removeToken(IERC20 token) external requiresAuth;
Parameters
token
IERC20
The token to be removed
Return maximum amount that can still be deposited
function maxDeposit() external view returns (uint256);
Returns
<none>
uint256
Amount of deposit capacity remaining
Check if a user's units are currently locked
function areUserUnitsLocked(address user) external view returns (bool);
Parameters
user
address
The address to check
Returns
<none>
bool
True if user's units are locked, false otherwise
Computes the hash for a sync deposit
function getDepositHash(address user, IERC20 token, uint256 tokenAmount, uint256 unitsAmount, uint256 refundableUntil)
external
pure
returns (bytes32);
Parameters
user
address
The address making the deposit
token
IERC20
The token being deposited
tokenAmount
uint256
The amount of tokens to deposit
unitsAmount
uint256
Minimum amount of units to receive
refundableUntil
uint256
The timestamp until which the deposit is refundable
Returns
<none>
bytes32
The hash of the deposit
Computes the hash for a generic request
function getRequestHash(IERC20 token, Request calldata request) external pure returns (bytes32);
Parameters
token
IERC20
The token involved in the request
request
Request
The request struct
Returns
<none>
bytes32
The hash of the request
Handles a synchronous deposit, records the deposit hash, and enters the vault
Reverts if the deposit hash already exists. Sets the refundable period for the user
function _syncDeposit(IERC20 token, uint256 tokenAmount, uint256 unitAmount) internal;
Parameters
token
IERC20
The ERC20 token to deposit
tokenAmount
uint256
The amount of tokens to deposit
unitAmount
uint256
The amount of vault units to mint for the user
Solves an async deposit request for the vault, transfering tokens or refunding as needed
Returns 0 if any of:
price age is too high, emits PriceAgeExceeded
request hash is not set, emits InvalidRequestHash
units out is less than min required, emits AmountBoundExceeded
deposit cap would be exceeded, emits DepositCapExceeded
If deadline not passed, processes deposit and emits DepositSolved
If deadline passed, refunds and emits DepositRefunded
Always unsets hash after processing*
function _solveDepositVaultAutoPrice(
IERC20 token,
uint256 depositMultiplier,
Request calldata request,
uint256 priceAge,
uint256 index
) internal returns (uint256 solverTip);
Parameters
token
IERC20
The ERC20 token being deposited
depositMultiplier
uint256
The multiplier (in BPS) applied to the deposit for premium calculation
request
Request
The deposit request struct containing all user parameters
priceAge
uint256
The age of the price data used for conversion
index
uint256
The index of the request in the given solving batch
Returns
solverTip
uint256
The tip amount paid to the solver, or 0 if not processed
Solves a fixed price deposit request for the vault, transfering tokens or refunding as needed
User gets exactly min units out, but may over‑fund, the difference is paid to the solver as a tip
Returns 0 if any of:
price age is too high, emits PriceAgeExceeded
request hash is not set, emits InvalidRequestHash
tokens needed exceed the maximum allowed, emits AmountBoundExceeded
deposit cap would be exceeded, emits DepositCapExceeded
If deadline not passed, processes deposit and emits DepositSolved
If deadline passed, refunds and emits DepositRefunded
Always unsets hash after processing*
function _solveDepositVaultFixedPrice(
IERC20 token,
uint256 depositMultiplier,
Request calldata request,
uint256 priceAge,
uint256 index
) internal returns (uint256 solverTip);
Parameters
token
IERC20
The ERC20 token being deposited
depositMultiplier
uint256
The multiplier (in BPS) applied to the deposit for premium calculation
request
Request
The deposit request struct containing all user parameters
priceAge
uint256
The age of the price data used for conversion
index
uint256
The index of the request in the given solving batch
Returns
solverTip
uint256
The tip amount paid to the solver, or 0 if not processed
Solves an async redeem request for the vault, transfering tokens or refunding as needed
Returns 0 if any of:
price age is too high, emits PriceAgeExceeded
request hash is not set, emits InvalidRequestHash
token out after premium is less than min required, emits AmountBoundExceeded
If deadline not passed, processes redeem and emits RedeemSolved
If deadline passed, refunds and emits RedeemRefunded
Always unsets hash after processing*
function _solveRedeemVaultAutoPrice(
IERC20 token,
uint256 redeemMultiplier,
Request calldata request,
uint256 priceAge,
uint256 index
) internal returns (uint256 solverTip);
Parameters
token
IERC20
The ERC20 token being redeemed
redeemMultiplier
uint256
The multiplier (in BPS) applied to the redeem for premium calculation
request
Request
The redeem request struct containing all user parameters
priceAge
uint256
The age of the price data used for conversion
index
uint256
The index of the request in the given solving batch
Returns
solverTip
uint256
The tip amount paid to the solver, or 0 if not processed
Solves a fixed price redeem request for the vault, transfering tokens or refunding as needed
User gets exactly min tokens out, but may under‑fund, the difference is paid to the solver as a tip
Returns 0 if any of:
price age is too high, emits PriceAgeExceeded
request hash is not set, emits InvalidRequestHash
If deadline not passed, processes redeem and emits RedeemSolved
If deadline passed, refunds and emits RedeemRefunded
Always unsets hash after processing*
function _solveRedeemVaultFixedPrice(
IERC20 token,
uint256 redeemMultiplier,
Request calldata request,
uint256 priceAge,
uint256 index
) internal returns (uint256 solverTip);
Parameters
token
IERC20
The ERC20 token being redeemed
redeemMultiplier
uint256
The multiplier (in BPS) applied to the redeem for premium calculation
request
Request
The redeem request struct containing all user parameters
priceAge
uint256
The age of the price data used for conversion
index
uint256
The index of the request in the given solving batch
Returns
solverTip
uint256
The tip amount paid to the solver, or 0 if not processed
Solves a direct deposit request, transfering tokens and units between users
Returns early if any of:
request hash is not set, emits InvalidRequestHash
If deadline not passed, transfers units and tokens, emits DepositSolved
If deadline passed, refunds tokens, emits DepositRefunded
Always unsets hash after processing*
function _solveDepositDirect(IERC20 token, Request calldata request) internal;
Parameters
token
IERC20
The ERC20 token being deposited
request
Request
The deposit request struct containing all user parameters
Solves a direct redeem request, transfering tokens and units between users
Returns early if:
request hash is not set, emits InvalidRequestHash
If deadline not passed, transfers units and tokens, emits RedeemSolved
If deadline passed, refunds units, emits RedeemRefunded
Always unsets hash after processing*
function _solveRedeemDirect(IERC20 token, Request calldata request) internal;
Parameters
token
IERC20
The ERC20 token being redeemed
request
Request
The redeem request struct containing all user parameters
Checks if the price age exceeds the maximum allowed and emits an event if so
function _guardPriceAge(uint256 priceAge, uint256 maxPriceAge, uint256 index) internal returns (bool);
Parameters
priceAge
uint256
The difference between when price was measured and submitted onchain
maxPriceAge
uint256
The maximum allowed price age
index
uint256
The index of the request in the given solving batch
Returns
<none>
bool
True if price age is too high, false otherwise
Checks if the request hash exists and emits an event if not
function _guardInvalidRequestHash(bool hashExists, bytes32 requestHash) internal returns (bool);
Parameters
hashExists
bool
Whether the hash exists
requestHash
bytes32
The request hash
Returns
<none>
bool
True if hash does not exist, false otherwise
Checks if there are enough tokens for the solver tip and emits an event if not
function _guardInsufficientTokensForTip(uint256 tokens, uint256 solverTip, uint256 index) internal returns (bool);
Parameters
tokens
uint256
The number of tokens
solverTip
uint256
The solver tip amount
index
uint256
The index of the request in the given solving batch
Returns
<none>
bool
True if not enough tokens for tip, false otherwise
Checks if the amount is less than the bound and emits an event if so
function _guardAmountBound(uint256 amount, uint256 bound, uint256 index) internal returns (bool);
Parameters
amount
uint256
The actual amount
bound
uint256
The minimum required amount
index
uint256
The index of the request in the given solving batch
Returns
<none>
bool
True if amount is less than bound, false otherwise
Checks if the deposit cap would be exceeded and emits an event if so
function _guardDepositCapExceeded(uint256 totalUnits, uint256 index) internal returns (bool);
Parameters
totalUnits
uint256
The total units after deposit
index
uint256
The index of the request in the given solving batch
Returns
<none>
bool
True if deposit cap would be exceeded, false otherwise
Reverts if sync deposits are not enabled for the token
function _requireSyncDepositsEnabled(IERC20 token) internal view returns (TokenDetails storage tokenDetails);
Parameters
token
IERC20
The ERC20 token to check
Returns
tokenDetails
TokenDetails
The token details storage reference
Reverts if deposit cap would be exceeded by adding units
function _requireDepositCapNotExceeded(uint256 units) internal view;
Parameters
units
uint256
The number of units to add
Checks if deposit cap would be exceeded by adding units
function _isDepositCapExceeded(uint256 units) internal view returns (bool);
Parameters
units
uint256
The number of units to add
Returns
<none>
bool
True if deposit cap would be exceeded, false otherwise
Converts token amount to units, applying multiplier and flooring
function _tokensToUnitsFloorIfActive(IERC20 token, uint256 tokens, uint256 multiplier)
internal
view
returns (uint256);
Parameters
token
IERC20
The ERC20 token
tokens
uint256
The amount of tokens
multiplier
uint256
The multiplier to apply
Returns
<none>
uint256
The resulting units (floored)
Converts units to token amount, applying multiplier and flooring
function _unitsToTokensFloorIfActive(IERC20 token, uint256 units, uint256 multiplier) internal view returns (uint256);
Parameters
token
IERC20
The ERC20 token
units
uint256
The amount of units
multiplier
uint256
The multiplier to apply
Returns
<none>
uint256
The resulting token amount (floored)
Converts units to token amount, applying multiplier and ceiling
function _unitsToTokensCeilIfActive(IERC20 token, uint256 units, uint256 multiplier) internal view returns (uint256);
Parameters
token
IERC20
The ERC20 token
units
uint256
The amount of units
multiplier
uint256
The multiplier to apply
Returns
<none>
uint256
The resulting token amount (ceiled)
Get the hash of a deposit
Since refundableUntil is block.timestamp + depositRefundTimeout (which is subject to change), it's theoretically possible to have a hash collision, but the probability is negligible and we optimize for the common case
function _getDepositHash(address user, IERC20 token, uint256 tokenAmount, uint256 unitsAmount, uint256 refundableUntil)
internal
pure
returns (bytes32);
Parameters
user
address
The user who made the deposit
token
IERC20
The token that was deposited
tokenAmount
uint256
The amount of tokens deposited
unitsAmount
uint256
The amount of units received
refundableUntil
uint256
The timestamp at which the deposit can be refunded
Returns
<none>
bytes32
The hash of the deposit
Get the hash of a request from parameters
function _getRequestHashParams(
IERC20 token,
address user,
RequestType requestType,
uint256 tokens,
uint256 units,
uint256 solverTip,
uint256 deadline,
uint256 maxPriceAge
) internal pure returns (bytes32);
Parameters
token
IERC20
The token that was deposited or redeemed
user
address
The user who made the request
requestType
RequestType
The type of request
tokens
uint256
The amount of tokens in the request
units
uint256
The amount of units in the request
solverTip
uint256
The tip paid to the solver
deadline
uint256
The deadline of the request
maxPriceAge
uint256
The maximum age of the price data
Returns
<none>
bytes32
The hash of the request
Get the hash of a request
function _getRequestHash(IERC20 token, Request calldata request) internal pure returns (bytes32);
Parameters
token
IERC20
The token that was deposited or redeemed
request
Request
The request to get the hash of
Returns
<none>
bytes32
The hash of the request
Returns true if the request type is a deposit
function _isRequestTypeDeposit(RequestType requestType) internal pure returns (bool);
Parameters
requestType
RequestType
The request type
Returns
<none>
bool
True if deposit, false otherwise
Returns true if the request type is fixed price
function _isRequestTypeAutoPrice(RequestType requestType) internal pure returns (bool);
Parameters
requestType
RequestType
The request type
Returns
<none>
bool
True if fixed price, false otherwise