aip | title | author | discussions-to | Status | last-call-end-date (*optional) | type | created | updated (*optional) | requires (*optional) |
---|---|---|---|---|---|---|---|---|---|
65 |
Storage Fee for State Bytes refundable |
msmouse |
In Review |
Gas |
12/12/2023 |
Proposed is an evolution of the Storage Fee charging scheme where a category of storage fee (dubbed "bytes deposit") is charged and refunded according to the number of bytes a state item itself occupies in the current state, in addition to the existing "slot deposit" which reflects the storage impact imposed by a individual state item via the authenticated data structures.
Specifically, the legacy "free quota" mechanism which heavily punishes updating a large state item is removed.
The updated scheme aligns better with the reality of disk space consumption by the transactions hence serves as a better economic benchmark for the developers to optimize the cost of transactions.
Generally speaking the Aptos nodes keep two categories of blockchain data on disk:
- The latest state: Items in the latest state and associated authentication data structures -- the network has to keep them around indefinitely until a transaction deleted the relevant state. Such storage should be priced high and is subject to refunding once deleted.
- The ledger history: the transaction itself and its outputs, including the "write set", which is the collection of the updated state items -- the entirety of the updated items.
Let's say, a large state item increases in size slightly:
- there's a small increase in the total size of the latest state.
- the entirety of the updated item will end up in the write set, which is part of the ledger hisotry, and lives on disk until the transaction version is old enough to be pruned.
Historically the storage fee charging scheme is designed to prevent both categories of storage consumption from filling the disk up for cheap. Specifically, to make sure the disk is not filled with the latest state items, storage fee for bytes was high; and to make sure disk is not filled with write sets generated by updating large items, the entirety of the updated state item is charged for the high rate; and finally, to make the cost of common use cases reasonable, there is a per item "free bytes qouta" of 1KB -- not only smaller items are cheaper to allocate, they are modified free of charge.
However, items larger than the free quota are very expensive to modify repeatedly.
The old scheme penalizes frequently modified large state items heavily hence brought strong incentives for items smaller than the free quota, which imposes awkward trade-offs for developers to design storage granularities of their contracts and potentially make the state explosion problem worse by incentivizing more state items.
With the introduction of AIP-57, which adds a limit to per block transaction output size, the disk bandwidth for writing down the ledger history is effectively upper bounded. As a result, the total disk space to store a specific length of ledger history (measured by days) is upper bounded. To simplify the model, we propose this part of cost to be deemed constant and not applicable for storage fee charges. As a result, the fee charge uppon the size of state item reflects only the permanent storage impact and should be charged incrementally as the item grow in size and refunded as the slot it occupies gets cleaned up.
Remove the per slot free quota and be more friendly to reasonable large items.
Notice that this AIP is about the Storage Fee which concerns disk space consumption. There's a related concern on the latency side of things which is covered by the Io Gas. Changes needed to be made on that front as well and that's covered by (AIP-59)[https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-59.md]
Frequently updated larger state items are now cheaper. And when deleted, fees paid for the bytes are refundable. As a result, the developer can now straightforwardly decide on storage granularity according to the access (modification) pattern of things without worrying about modifying larger items being punished.
Pricing is reduced to 4000 octas per slot and 40 octas per byte and the 1KB free quota is removed. As a result:
- Allocating an item smaller than 250 bytes is cheaper than before.
- Allocating an item of the size between 250 to 4K bytes will be slightly more expensive than before, but more fair. The price increase peaks at 1KB at about 60%
- Merely touching a slot > 1KB no longer imposes penalty so such txns get significantly cheaper. As seen in MutateLargeTokenV2, UpgradeLarge, etc in the table below.
Before vs. After gas cost for common transaction types (assuming gas_unit_price=100 octas):
original 5k/slot 50/byte w/ 1KB free quota | 4k/slot 40/byte | |||
---|---|---|---|---|
Transfer | 6 | 6 | 100.0% | |
2ndTransfer | 6 | 6 | 100.0% | |
CreateAccount | 1004 | 992 | 98.8% | |
CreateTransfer | 1006 | 994 | 98.8% | |
MintTokenV2 | 511 | 633 | 123.9% | |
MutateTokenV2 | 7 | 7 | 100.0% | |
MintLargeTokenV2 | 1620 | 1453 | 89.7% | |
MutateLargeTokenV2 | 1755 | 9 | 0.5% | |
CreateStakePool | 2018 | 2347 | 116.3% | |
RotateConsensusKey | 45 | 64 | 142.2% | |
JoinValidator100 | 4559 | 51 | 1.1% | |
AddStake | 4561 | 13 | 0.3% | |
UnlockStake | 9 | 38 | 422.2% | |
WithdrawStake | 9 | 9 | 100.0% | |
LeaveValidatorSet100 | 4558 | 10 | 0.2% | |
CreateCollection | 1006 | 962 | 95.6% | |
CreateTokenFirstTime | 1509 | 1489 | 98.7% | |
MintTokenV1 | 8 | 8 | 100.0% | |
MutateTokenV1 | 509 | 483 | 94.9% | |
MutateTokenV12ndTime | 8 | 8 | 100.0% | |
MutateTokenAdd10NewProperties | 12 | 64 | 533.3% | |
MutateTokenMutate10ExistingProperties | 12 | 12 | 100.0% | |
PublishSmall | 1065 | 1122 | 105.4% | |
UpgradeSmall | 71 | 70 | 98.6% | |
PublishLarge | 13166 | 11055 | 84.0% | |
UpgradeLarge | 10812 | 1443 | 13.3% |
N/A
- The per slot "free bytes" quota is removed. Instead, all the bytes of a state item are priced uniformly for the permanent space occupation in the state DB.
- Treat storage fee for bytes as deposit, which is refundable.
- When a slot increases in size on modification, charge additionally into the deposit.
- legacy slots that didn't pay bytes deposits won't get charged for the bytes allocated for free.
- Considering pricing change, charge only to the point where the total deposit for bytes doesn't go beyond
current_price_per_byte * num_current_bytes
- When slot decrease in size, don't refund, to simplify implementation and reasoning.
- If slot doesn't change in size on modification, no charging even if pricing changes.
- Refund only on deletion.
Due to pricing change, certain transactions got pricier. Specifically, those allocates (not modifying) slots that's larger than 250 bytes and smaller than 4K bytes. But it's more fair.
Release 1.10, early 2024
Release 1.10, early 2024
Permanent storage price is lowered by 20%, which we think is worth the trade offs.