Skip to content

Storage

Everything the engine stores takes storage on NEAR, which locks NEAR in the contract’s account. The engine charges this to a storage balance: NEAR deposited for storage only. An asset registration is charged to the account that makes it, even for someone else, and a DEX’s code and data to the DEX. Storage balances are separate from inner balances: NEAR in your storage balance can’t be traded, and NEAR in your inner balance doesn’t pay for storage.

There are two kinds of storage balances, both work like NEP-145:

Accounts DEXs
Pays for Asset registrations the account makes The DEX’s code and everything the DEX stores
Deposit storage_deposit dex_storage_deposit
Withdraw storage_withdraw, by the account dex_storage_withdraw, by the DEX’s deployer
View storage_balance_of dex_storage_balance_of

Each storage balance has a total (deposited) and an available part (not used yet). When storage is freed, its cost goes back to available.

If an action needs more storage than is available, it fails with Storage used (<used>) exceeds total (<total>). Deposit more and try again.

Your storage balance pays for registering assets, for yourself or for anyone else. Holding, receiving and trading registered assets doesn’t use more storage.

near contract call-function as-transaction dex.intear.near storage_deposit \
json-args '{"account_id": "alice.near", "registration_only": false}' \
prepaid-gas '30.0 Tgas' attached-deposit '0.01 NEAR' \
sign-as alice.near network-config mainnet sign-with-keychain send
  • account_id is optional and defaults to you. Anyone can deposit for any account.
  • The deposit must be at least 0.005 NEAR (storage_balance_bounds returns the exact minimum, there’s no maximum).
  • With "registration_only": true, only 0.005 NEAR is kept and the rest is refunded. If the account already has a storage balance, the whole deposit is refunded.

For example, to pay for the storage of bob.near, but only if they have none yet:

near contract call-function as-transaction dex.intear.near storage_deposit \
json-args '{"account_id": "bob.near", "registration_only": true}' \
prepaid-gas '30.0 Tgas' attached-deposit '0.005 NEAR' \
sign-as alice.near network-config mainnet sign-with-keychain send

storage_deposit returns the new balance, and so does storage_balance_of:

near contract call-function as-read-only dex.intear.near storage_balance_of \
json-args '{"account_id": "alice.near"}' \
network-config mainnet now
{ "total": "10000000000000000000000", "available": "..." }

available is a bit less than total after the first deposit: the storage balance itself takes storage.

Storage costs 0.00001 NEAR per byte, so how much you need depends on the lengths of the account and asset IDs. Roughly:

What Storage
The storage balance itself 0.0008 to 0.0014 NEAR
The first registration of an account 0.0008 to 0.0026 NEAR more
Each near or NEP-141 asset 0.0015 to 0.0028 NEAR, more if nobody registered it before

So 0.005 NEAR, what registration_only keeps, doesn’t cover two assets for most accounts: bob.near needs 0.00506 NEAR for near and USDt. 0.01 NEAR covers any two near or NEP-141 assets that are already registered for someone.

To get unused NEAR back, call storage_withdraw with 1 yoctoNEAR attached. amount is optional and defaults to everything available:

near contract call-function as-transaction dex.intear.near storage_withdraw \
json-args '{"amount": "5000000000000000000000"}' \
prepaid-gas '30.0 Tgas' attached-deposit '1 yoctoNEAR' \
sign-as alice.near network-config mainnet sign-with-keychain send

storage_unregister is not supported: registrations can’t be undone.

A DEX’s storage balance pays for its code and for all the data the DEX stores, such as pools and liquidity positions. When a swap or a call makes a DEX store more, the cost comes from the DEX’s storage balance, not from the trader’s.

Anyone can top it up:

near contract call-function as-transaction dex.intear.near dex_storage_deposit \
json-args '{"dex_id": "slimedragon.near/xyk", "registration_only": false}' \
prepaid-gas '30.0 Tgas' attached-deposit '1 NEAR' \
sign-as alice.near network-config mainnet sign-with-keychain send
near contract call-function as-read-only dex.intear.near dex_storage_balance_of \
json-args '{"dex_id": "slimedragon.near/xyk"}' \
network-config mainnet now

Only the deployer of a DEX (slimedragon.near for slimedragon.near/xyk) can withdraw from it, with 1 yoctoNEAR attached:

near contract call-function as-transaction dex.intear.near dex_storage_withdraw \
json-args '{"dex_id": "slimedragon.near/xyk", "amount": "1000000000000000000000000"}' \
prepaid-gas '30.0 Tgas' attached-deposit '1 yoctoNEAR' \
sign-as slimedragon.near network-config mainnet sign-with-keychain send

amount is optional and defaults to everything available.

A DEX can also turn NEAR from its inner balance into storage balance itself, and a StorageDeposit operation does the same from your inner balance, for any account or DEX.

total_storage_balances returns the sum of all storage balances:

near contract call-function as-read-only dex.intear.near total_storage_balances \
json-args '{}' \
network-config mainnet now
{
"users": { "total": "...", "available": "..." },
"dexes": { "total": "...", "available": "..." }
}