Skip to main content

VaultV2

The VaultV2 contract is an ERC-4626 compliant vault that implements advanced asset allocation strategies across multiple adapters, fee management, timelock-protected governance, and flexible access controls.

Overview

VaultV2 extends the ERC-4626 standard with:
  • Multi-adapter allocation system with configurable caps
  • Timelock-protected curator functions
  • Role-based access control (owner, curator, allocators, sentinels)
  • Performance and management fee accrual
  • Gate-based transfer restrictions
  • ERC-2612 permit functionality

Immutable variables

asset
address
The address of the underlying ERC-20 asset managed by the vault
decimals
uint8
The number of decimals used for vault shares (assetDecimals + decimalOffset, where decimalOffset = max(0, 18 - assetDecimals))
virtualShares
uint256
Virtual shares used for inflation attack protection (equals 10^decimalOffset)

State variables

Role storage

owner
address
The vault owner who can set the curator and sentinels
curator
address
The curator who can submit timelocked configuration changes
receiveSharesGate
address
Gate contract that controls who can receive vault shares (address(0) disables)
sendSharesGate
address
Gate contract that controls who can send vault shares (address(0) disables)
receiveAssetsGate
address
Gate contract that controls who can receive assets from the vault (address(0) disables)
sendAssetsGate
address
Gate contract that controls who can send assets to the vault (address(0) disables)
adapterRegistry
address
Registry contract that validates adapters (address(0) allows any adapter)
isSentinel
mapping(address => bool)
Mapping of accounts that have sentinel privileges (can revoke timelocked operations and decrease caps)
isAllocator
mapping(address => bool)
Mapping of accounts that can allocate assets across adapters

Token storage

name
string
The name of the vault token
symbol
string
The symbol of the vault token
totalSupply
uint256
Total supply of vault shares (excludes unminted fee shares)
balanceOf
mapping(address => uint256)
Mapping of account balances
allowance
mapping(address => mapping(address => uint256))
Mapping of spending allowances
nonces
mapping(address => uint256)
Nonces for ERC-2612 permit functionality

Interest storage

firstTotalAssets
uint256
Total assets after first interest accrual in the current transaction (transient storage)
_totalAssets
uint128
Last recorded total assets (use totalAssets() for current value)
lastUpdate
uint64
Timestamp of last interest accrual
maxRate
uint64
Maximum rate at which share price can increase per second (in WAD)

Curation storage

isAdapter
mapping(address => bool)
Mapping of enabled adapters
adapters
address[]
Array of adapter addresses
forceDeallocatePenalty
mapping(address => uint256)
Penalty (in WAD) for force deallocating from each adapter

Liquidity adapter storage

liquidityAdapter
address
Adapter used for deposits and withdrawals
liquidityData
bytes
Data passed to the liquidity adapter

Timelock storage

timelock
mapping(bytes4 => uint256)
Timelock duration for each function selector
abdicated
mapping(bytes4 => bool)
Functions that have been permanently disabled
executableAt
mapping(bytes => uint256)
Timestamp when each timelocked operation can be executed

Fee storage

performanceFee
uint96
Performance fee in WAD (max 50%)
performanceFeeRecipient
address
Recipient of performance fees
managementFee
uint96
Management fee per second in WAD (max 5% APR)
managementFeeRecipient
address
Recipient of management fees

View functions

adaptersLength

function adaptersLength() external view returns (uint256)
Returns the number of adapters.
uint256
The length of the adapters array

totalAssets

function totalAssets() external view returns (uint256)
Returns the total assets managed by the vault after accruing interest.
uint256
The current total assets including accrued interest

DOMAIN_SEPARATOR

function DOMAIN_SEPARATOR() public view returns (bytes32)
Returns the EIP-712 domain separator for permit signatures.
bytes32
The domain separator hash

absoluteCap

function absoluteCap(bytes32 id) external view returns (uint256)
Returns the absolute cap for a given allocation ID.
id
bytes32
The allocation ID (keccak256 hash of idData)
uint256
The absolute cap in asset units

relativeCap

function relativeCap(bytes32 id) external view returns (uint256)
Returns the relative cap for a given allocation ID.
id
bytes32
The allocation ID
uint256
The relative cap in WAD (relative to firstTotalAssets)

allocation

function allocation(bytes32 id) external view returns (uint256)
Returns the current allocation for a given ID.
id
bytes32
The allocation ID
uint256
The current allocation amount

accrueInterestView

function accrueInterestView() public view returns (uint256, uint256, uint256)
Calculates accrued interest and fees without updating state.
newTotalAssets
uint256
The total assets after interest accrual
performanceFeeShares
uint256
Shares to mint for performance fees
managementFeeShares
uint256
Shares to mint for management fees

previewDeposit

function previewDeposit(uint256 assets) public view returns (uint256)
Previews the number of shares that would be minted for a deposit.
assets
uint256
The amount of assets to deposit
uint256
The number of shares that would be minted

previewMint

function previewMint(uint256 shares) public view returns (uint256)
Previews the amount of assets required to mint a given number of shares.
shares
uint256
The number of shares to mint
uint256
The amount of assets required

previewWithdraw

function previewWithdraw(uint256 assets) public view returns (uint256)
Previews the number of shares that would be burned for a withdrawal.
assets
uint256
The amount of assets to withdraw
uint256
The number of shares that would be burned

previewRedeem

function previewRedeem(uint256 shares) public view returns (uint256)
Previews the amount of assets that would be withdrawn for redeeming shares.
shares
uint256
The number of shares to redeem
uint256
The amount of assets that would be withdrawn

convertToShares

function convertToShares(uint256 assets) external view returns (uint256)
Converts assets to shares (rounded down), accounting for fees.
assets
uint256
The amount of assets
uint256
The equivalent number of shares

convertToAssets

function convertToAssets(uint256 shares) external view returns (uint256)
Converts shares to assets (rounded down), accounting for fees.
shares
uint256
The number of shares
uint256
The equivalent amount of assets

maxDeposit

function maxDeposit(address) external pure returns (uint256)
Returns the maximum deposit amount (always 0 due to gate uncertainty).
uint256
Always returns 0

maxMint

function maxMint(address) external pure returns (uint256)
Returns the maximum mint amount (always 0 due to gate uncertainty).
uint256
Always returns 0

maxWithdraw

function maxWithdraw(address) external pure returns (uint256)
Returns the maximum withdrawal amount (always 0 due to gate uncertainty).
uint256
Always returns 0

maxRedeem

function maxRedeem(address) external pure returns (uint256)
Returns the maximum redeem amount (always 0 due to gate uncertainty).
uint256
Always returns 0

canReceiveShares

function canReceiveShares(address account) public view returns (bool)
Checks if an account can receive vault shares.
account
address
The account to check
bool
True if the account can receive shares

canSendShares

function canSendShares(address account) public view returns (bool)
Checks if an account can send vault shares.
account
address
The account to check
bool
True if the account can send shares

canReceiveAssets

function canReceiveAssets(address account) public view returns (bool)
Checks if an account can receive assets from the vault.
account
address
The account to check
bool
True if the account can receive assets (vault itself is always allowed)

canSendAssets

function canSendAssets(address account) public view returns (bool)
Checks if an account can send assets to the vault.
account
address
The account to check
bool
True if the account can send assets

Constructor

constructor(address _owner, address _asset)
Initializes a new VaultV2 instance.
_owner
address
The initial owner of the vault
_asset
address
The underlying ERC-20 asset address

Public functions

multicall

function multicall(bytes[] calldata data) external
Executes multiple calls in a single transaction using delegatecall.
data
bytes[]
Array of encoded function calls

accrueInterest

function accrueInterest() public
Accrues interest and mints fee shares. Called automatically on first interaction per transaction.

Owner functions

These functions can only be called by the vault owner.

setOwner

function setOwner(address newOwner) external
Sets a new owner.
newOwner
address
The address of the new owner

setCurator

function setCurator(address newCurator) external
Sets a new curator.
newCurator
address
The address of the new curator

setIsSentinel

function setIsSentinel(address account, bool newIsSentinel) external
Grants or revokes sentinel role.
account
address
The account to update
newIsSentinel
bool
True to grant sentinel role, false to revoke

setName

function setName(string memory newName) external
Sets the vault token name.
newName
string
The new token name

setSymbol

function setSymbol(string memory newSymbol) external
Sets the vault token symbol.
newSymbol
string
The new token symbol

Timelock functions

These functions manage the timelock system for curator functions.

submit

function submit(bytes calldata data) external
Submits a timelocked operation. Can only be called by the curator.
data
bytes
The encoded function call data

revoke

function revoke(bytes calldata data) external
Revokes a pending timelocked operation. Can be called by curator or sentinels.
data
bytes
The encoded function call data to revoke

Curator functions

These functions are timelocked and can only be executed by the curator after the timelock expires.

setIsAllocator

function setIsAllocator(address account, bool newIsAllocator) external
Grants or revokes allocator role (timelocked).
account
address
The account to update
newIsAllocator
bool
True to grant allocator role, false to revoke

setReceiveSharesGate

function setReceiveSharesGate(address newReceiveSharesGate) external
Sets the receive shares gate (timelocked).
newReceiveSharesGate
address
The new gate address (address(0) to disable)

setSendSharesGate

function setSendSharesGate(address newSendSharesGate) external
Sets the send shares gate (timelocked).
newSendSharesGate
address
The new gate address (address(0) to disable)

setReceiveAssetsGate

function setReceiveAssetsGate(address newReceiveAssetsGate) external
Sets the receive assets gate (timelocked).
newReceiveAssetsGate
address
The new gate address (address(0) to disable)

setSendAssetsGate

function setSendAssetsGate(address newSendAssetsGate) external
Sets the send assets gate (timelocked).
newSendAssetsGate
address
The new gate address (address(0) to disable)

setAdapterRegistry

function setAdapterRegistry(address newAdapterRegistry) external
Sets the adapter registry (timelocked). Validates existing adapters against the new registry.
newAdapterRegistry
address
The new adapter registry address (address(0) to disable)

addAdapter

function addAdapter(address account) external
Adds an adapter (timelocked). Validates against adapter registry if set.
account
address
The adapter address to add

removeAdapter

function removeAdapter(address account) external
Removes an adapter (timelocked).
account
address
The adapter address to remove

increaseTimelock

function increaseTimelock(bytes4 selector, uint256 newDuration) external
Increases the timelock duration for a function (timelocked).
selector
bytes4
The function selector (cannot be decreaseTimelock)
newDuration
uint256
The new timelock duration in seconds

decreaseTimelock

function decreaseTimelock(bytes4 selector, uint256 newDuration) external
Decreases the timelock duration for a function (timelocked with the original function’s timelock).
selector
bytes4
The function selector (cannot be decreaseTimelock)
newDuration
uint256
The new timelock duration in seconds

abdicate

function abdicate(bytes4 selector) external
Permanently disables a timelocked function (timelocked).
selector
bytes4
The function selector to abdicate

setPerformanceFee

function setPerformanceFee(uint256 newPerformanceFee) external
Sets the performance fee (timelocked). Accrues interest before changing.
newPerformanceFee
uint256
The new performance fee in WAD (max 0.5e18 = 50%)

setManagementFee

function setManagementFee(uint256 newManagementFee) external
Sets the management fee (timelocked). Accrues interest before changing.
newManagementFee
uint256
The new management fee per second in WAD (max 5% APR)

setPerformanceFeeRecipient

function setPerformanceFeeRecipient(address newPerformanceFeeRecipient) external
Sets the performance fee recipient (timelocked). Accrues interest before changing.
newPerformanceFeeRecipient
address
The new recipient address

setManagementFeeRecipient

function setManagementFeeRecipient(address newManagementFeeRecipient) external
Sets the management fee recipient (timelocked). Accrues interest before changing.
newManagementFeeRecipient
address
The new recipient address

increaseAbsoluteCap

function increaseAbsoluteCap(bytes memory idData, uint256 newAbsoluteCap) external
Increases the absolute cap for an allocation ID (timelocked).
idData
bytes
The allocation ID data (hashed to get the ID)
newAbsoluteCap
uint256
The new absolute cap

decreaseAbsoluteCap

function decreaseAbsoluteCap(bytes memory idData, uint256 newAbsoluteCap) external
Decreases the absolute cap for an allocation ID. Can be called by curator or sentinels (not timelocked for sentinels).
idData
bytes
The allocation ID data
newAbsoluteCap
uint256
The new absolute cap

increaseRelativeCap

function increaseRelativeCap(bytes memory idData, uint256 newRelativeCap) external
Increases the relative cap for an allocation ID (timelocked).
idData
bytes
The allocation ID data
newRelativeCap
uint256
The new relative cap in WAD (max 1e18 = 100%)

decreaseRelativeCap

function decreaseRelativeCap(bytes memory idData, uint256 newRelativeCap) external
Decreases the relative cap for an allocation ID. Can be called by curator or sentinels (not timelocked for sentinels).
idData
bytes
The allocation ID data
newRelativeCap
uint256
The new relative cap in WAD

setForceDeallocatePenalty

function setForceDeallocatePenalty(address adapter, uint256 newForceDeallocatePenalty) external
Sets the penalty for force deallocating from an adapter (timelocked).
adapter
address
The adapter address
newForceDeallocatePenalty
uint256
The penalty in WAD (max 0.02e18 = 2%)

Allocator functions

These functions can be called by accounts with the allocator role.

allocate

function allocate(address adapter, bytes memory data, uint256 assets) external
Allocates assets to an adapter. Checks caps after allocation.
adapter
address
The adapter address
data
bytes
Data to pass to the adapter
assets
uint256
Amount of assets to allocate

deallocate

function deallocate(address adapter, bytes memory data, uint256 assets) external
Deallocates assets from an adapter. Can also be called by sentinels.
adapter
address
The adapter address
data
bytes
Data to pass to the adapter
assets
uint256
Amount of assets to deallocate

setLiquidityAdapterAndData

function setLiquidityAdapterAndData(address newLiquidityAdapter, bytes memory newLiquidityData) external
Sets the liquidity adapter and data used for deposits and withdrawals.
newLiquidityAdapter
address
The new liquidity adapter address
newLiquidityData
bytes
The data to pass to the liquidity adapter

setMaxRate

function setMaxRate(uint256 newMaxRate) external
Sets the maximum rate at which the share price can increase. Accrues interest before changing.
newMaxRate
uint256
The new max rate per second in WAD (max 200% APR)

User functions

deposit

function deposit(uint256 assets, address onBehalf) external returns (uint256)
Deposits assets and mints shares.
assets
uint256
Amount of assets to deposit
onBehalf
address
Address to receive the shares
uint256
Number of shares minted

mint

function mint(uint256 shares, address onBehalf) external returns (uint256)
Mints exact shares by depositing assets.
shares
uint256
Number of shares to mint
onBehalf
address
Address to receive the shares
uint256
Amount of assets deposited

withdraw

function withdraw(uint256 assets, address receiver, address onBehalf) public returns (uint256)
Withdraws exact assets by burning shares.
assets
uint256
Amount of assets to withdraw
receiver
address
Address to receive the assets
onBehalf
address
Address to burn shares from
uint256
Number of shares burned

redeem

function redeem(uint256 shares, address receiver, address onBehalf) external returns (uint256)
Redeems shares for assets.
shares
uint256
Number of shares to redeem
receiver
address
Address to receive the assets
onBehalf
address
Address to burn shares from
uint256
Amount of assets withdrawn

forceDeallocate

function forceDeallocate(address adapter, bytes memory data, uint256 assets, address onBehalf) external returns (uint256)
Forces deallocation from an adapter and applies a penalty. Useful for exiting when liquidity is limited.
adapter
address
The adapter to deallocate from
data
bytes
Data to pass to the adapter
assets
uint256
Amount of assets to deallocate
onBehalf
address
Address to apply the penalty to
uint256
Number of penalty shares withdrawn

ERC-20 functions

transfer

function transfer(address to, uint256 shares) external returns (bool)
Transfers shares to another address.
to
address
The recipient address
shares
uint256
Number of shares to transfer
bool
Always returns true (reverts on failure)

transferFrom

function transferFrom(address from, address to, uint256 shares) external returns (bool)
Transfers shares from one address to another.
from
address
The sender address
to
address
The recipient address
shares
uint256
Number of shares to transfer
bool
Always returns true (reverts on failure)

approve

function approve(address spender, uint256 shares) external returns (bool)
Approves an address to spend shares.
spender
address
The address to approve
shares
uint256
Number of shares to approve
bool
Always returns true (reverts on failure)

permit

function permit(address _owner, address spender, uint256 shares, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external
Approves spending via EIP-2612 signature.
_owner
address
The token owner
spender
address
The address to approve
shares
uint256
Number of shares to approve
deadline
uint256
Expiration timestamp
v
uint8
Signature v parameter
r
bytes32
Signature r parameter
s
bytes32
Signature s parameter

Events

Constructor

event Constructor(address indexed owner, address indexed asset)
Emitted when the vault is created.

SetOwner

event SetOwner(address indexed newOwner)
Emitted when the owner is changed.

SetCurator

event SetCurator(address indexed newCurator)
Emitted when the curator is changed.

SetIsSentinel

event SetIsSentinel(address indexed account, bool newIsSentinel)
Emitted when a sentinel role is granted or revoked.

SetName

event SetName(string newName)
Emitted when the token name is changed.

SetSymbol

event SetSymbol(string newSymbol)
Emitted when the token symbol is changed.

Submit

event Submit(bytes4 indexed selector, bytes data, uint256 executableAt)
Emitted when a timelocked operation is submitted.

Revoke

event Revoke(address indexed sender, bytes4 indexed selector, bytes data)
Emitted when a timelocked operation is revoked.

Accept

event Accept(bytes4 indexed selector, bytes data)
Emitted when a timelocked operation is executed.

SetIsAllocator

event SetIsAllocator(address indexed account, bool newIsAllocator)
Emitted when an allocator role is granted or revoked.

SetReceiveSharesGate

event SetReceiveSharesGate(address indexed newReceiveSharesGate)
Emitted when the receive shares gate is changed.

SetSendSharesGate

event SetSendSharesGate(address indexed newSendSharesGate)
Emitted when the send shares gate is changed.

SetReceiveAssetsGate

event SetReceiveAssetsGate(address indexed newReceiveAssetsGate)
Emitted when the receive assets gate is changed.

SetSendAssetsGate

event SetSendAssetsGate(address indexed newSendAssetsGate)
Emitted when the send assets gate is changed.

SetAdapterRegistry

event SetAdapterRegistry(address indexed newAdapterRegistry)
Emitted when the adapter registry is changed.

AddAdapter

event AddAdapter(address indexed account)
Emitted when an adapter is added.

RemoveAdapter

event RemoveAdapter(address indexed account)
Emitted when an adapter is removed.

IncreaseTimelock

event IncreaseTimelock(bytes4 indexed selector, uint256 newDuration)
Emitted when a function’s timelock duration is increased.

DecreaseTimelock

event DecreaseTimelock(bytes4 indexed selector, uint256 newDuration)
Emitted when a function’s timelock duration is decreased.

Abdicate

event Abdicate(bytes4 indexed selector)
Emitted when a function is abdicated.

SetPerformanceFee

event SetPerformanceFee(uint256 newPerformanceFee)
Emitted when the performance fee is changed.

SetPerformanceFeeRecipient

event SetPerformanceFeeRecipient(address indexed newPerformanceFeeRecipient)
Emitted when the performance fee recipient is changed.

SetManagementFee

event SetManagementFee(uint256 newManagementFee)
Emitted when the management fee is changed.

SetManagementFeeRecipient

event SetManagementFeeRecipient(address indexed newManagementFeeRecipient)
Emitted when the management fee recipient is changed.

IncreaseAbsoluteCap

event IncreaseAbsoluteCap(bytes32 indexed id, bytes idData, uint256 newAbsoluteCap)
Emitted when an absolute cap is increased.

DecreaseAbsoluteCap

event DecreaseAbsoluteCap(address indexed sender, bytes32 indexed id, bytes idData, uint256 newAbsoluteCap)
Emitted when an absolute cap is decreased.

IncreaseRelativeCap

event IncreaseRelativeCap(bytes32 indexed id, bytes idData, uint256 newRelativeCap)
Emitted when a relative cap is increased.

DecreaseRelativeCap

event DecreaseRelativeCap(address indexed sender, bytes32 indexed id, bytes idData, uint256 newRelativeCap)
Emitted when a relative cap is decreased.

SetForceDeallocatePenalty

event SetForceDeallocatePenalty(address indexed adapter, uint256 forceDeallocatePenalty)
Emitted when a force deallocate penalty is set.

Allocate

event Allocate(address indexed sender, address indexed adapter, uint256 assets, bytes32[] ids, int256 change)
Emitted when assets are allocated to an adapter.

Deallocate

event Deallocate(address indexed sender, address indexed adapter, uint256 assets, bytes32[] ids, int256 change)
Emitted when assets are deallocated from an adapter.

ForceDeallocate

event ForceDeallocate(address indexed sender, address adapter, uint256 assets, address indexed onBehalf, bytes32[] ids, uint256 penaltyAssets)
Emitted when assets are force deallocated with a penalty.

SetLiquidityAdapterAndData

event SetLiquidityAdapterAndData(address indexed sender, address indexed newLiquidityAdapter, bytes indexed newLiquidityData)
Emitted when the liquidity adapter and data are changed.

SetMaxRate

event SetMaxRate(uint256 newMaxRate)
Emitted when the max rate is changed.

AccrueInterest

event AccrueInterest(uint256 previousTotalAssets, uint256 newTotalAssets, uint256 performanceFeeShares, uint256 managementFeeShares)
Emitted when interest is accrued.

Deposit

event Deposit(address indexed sender, address indexed onBehalf, uint256 assets, uint256 shares)
Emitted when assets are deposited.

Withdraw

event Withdraw(address indexed sender, address indexed receiver, address indexed onBehalf, uint256 assets, uint256 shares)
Emitted when assets are withdrawn.

Transfer

event Transfer(address indexed from, address indexed to, uint256 shares)
Emitted when shares are transferred.

Approval

event Approval(address indexed owner, address indexed spender, uint256 shares)
Emitted when an approval is made.

AllowanceUpdatedByTransferFrom

event AllowanceUpdatedByTransferFrom(address indexed owner, address indexed spender, uint256 shares)
Emitted when allowance is updated by transferFrom.

Permit

event Permit(address indexed owner, address indexed spender, uint256 shares, uint256 nonce, uint256 deadline)
Emitted when a permit is used.

Errors

The VaultV2 contract uses the following custom errors from ErrorsLib:
  • Abdicated() - Function has been abdicated
  • AbsoluteCapExceeded() - Allocation exceeds absolute cap
  • AbsoluteCapNotDecreasing() - New absolute cap is not decreasing
  • AbsoluteCapNotIncreasing() - New absolute cap is not increasing
  • AutomaticallyTimelocked() - Cannot modify timelock of decreaseTimelock
  • CannotReceiveShares() - Account cannot receive shares (gate restriction)
  • CannotReceiveAssets() - Account cannot receive assets (gate restriction)
  • CannotSendShares() - Account cannot send shares (gate restriction)
  • CannotSendAssets() - Account cannot send assets (gate restriction)
  • DataAlreadyPending() - Operation already submitted
  • DataNotTimelocked() - Operation not submitted for timelock
  • FeeInvariantBroken() - Fee recipient required when fee is non-zero
  • FeeTooHigh() - Fee exceeds maximum allowed
  • InvalidSigner() - Permit signature is invalid
  • MaxRateTooHigh() - Max rate exceeds allowed maximum
  • NotAdapter() - Address is not an approved adapter
  • NotInAdapterRegistry() - Adapter not in registry
  • PenaltyTooHigh() - Force deallocate penalty exceeds maximum
  • PermitDeadlineExpired() - Permit deadline has passed
  • RelativeCapAboveOne() - Relative cap exceeds 100%
  • RelativeCapExceeded() - Allocation exceeds relative cap
  • RelativeCapNotDecreasing() - New relative cap is not decreasing
  • RelativeCapNotIncreasing() - New relative cap is not increasing
  • TimelockNotDecreasing() - New timelock is not decreasing
  • TimelockNotExpired() - Timelock period has not expired
  • TimelockNotIncreasing() - New timelock is not increasing
  • Unauthorized() - Caller is not authorized
  • ZeroAbsoluteCap() - Cannot allocate to ID with zero absolute cap
  • ZeroAddress() - Address cannot be zero
  • ZeroAllocation() - Cannot deallocate from ID with zero allocation

Constants

  • WAD - 1e18 (used for fee and rate calculations)
  • MAX_MAX_RATE - 200% APR (maximum allowed maxRate)
  • MAX_PERFORMANCE_FEE - 0.5e18 (50%, maximum performance fee)
  • MAX_MANAGEMENT_FEE - 0.05e18 / 365 days (5% APR, maximum management fee)
  • MAX_FORCE_DEALLOCATE_PENALTY - 0.02e18 (2%, maximum force deallocate penalty)