From 05f0c946a804ea97a05a564173e8078a3a136825 Mon Sep 17 00:00:00 2001 From: bkchr Date: Fri, 12 Jan 2024 00:53:50 +0000 Subject: [PATCH] deploy: ade390b5ef06f3d897a56acea653504e706fe30e --- 404.html | 2 +- approved/0001-agile-coretime.html | 2 +- approved/0005-coretime-interface.html | 2 +- approved/0007-system-collator-selection.html | 2 +- approved/0008-parachain-bootnodes-dht.html | 2 +- ...12-process-for-adding-new-collectives.html | 2 +- ...rove-locking-mechanism-for-parachains.html | 2 +- approved/0022-adopt-encointer-runtime.html | 2 +- approved/0032-minimal-relay.html | 2 +- approved/0050-fellowship-salaries.html | 2 +- ...0056-one-transaction-per-notification.html | 6 +- index.html | 2 +- introduction.html | 2 +- print.html | 846 ++++++++++-------- ...l => 000x-lowering-deposits-assethub.html} | 189 ++-- proposed/0026-sassafras-consensus.html | 6 +- ...-absolute-location-account-derivation.html | 2 +- proposed/0042-extrinsics-state-version.html | 2 +- proposed/0044-rent-based-registration.html | 2 +- .../0046-metadata-for-offline-signers.html | 2 +- ...047-assignment-of-availability-chunks.html | 3 +- .../0059-nodes-capabilities-discovery.html | 2 +- .../0061-allocator-inside-of-runtime.html | 2 +- ...ering-existential-deposit-on-assethub.html | 6 +- searchindex.js | 2 +- searchindex.json | 2 +- ...04-remove-unnecessary-allocator-usage.html | 10 +- ...namic-pricing-for-bulk-coretime-sales.html | 6 +- ...09-improved-net-light-client-requests.html | 2 +- stale/0010-burn-coretime-revenue.html | 2 +- ...ath-to-account-creation-on-asset-hubs.html | 2 +- ...uilder-and-core-runtime-apis-for-mbms.html | 2 +- stale/0015-market-design-revisit.html | 2 +- ...irmation-period-duration-modification.html | 2 +- ...ction-voting-delegation-modifications.html | 2 +- .../0043-storage-proof-size-hostfunction.html | 2 +- stale/0048-session-keys-runtime-api.html | 2 +- stale/0054-remove-heap-pages.html | 2 +- 38 files changed, 626 insertions(+), 506 deletions(-) rename proposed/{000x-assethub.html => 000x-lowering-deposits-assethub.html} (55%) rename {proposed => stale}/0004-remove-unnecessary-allocator-usage.html (90%) diff --git a/404.html b/404.html index b11c02b..4e17be0 100644 --- a/404.html +++ b/404.html @@ -91,7 +91,7 @@ diff --git a/approved/0001-agile-coretime.html b/approved/0001-agile-coretime.html index a066a83..bf68210 100644 --- a/approved/0001-agile-coretime.html +++ b/approved/0001-agile-coretime.html @@ -90,7 +90,7 @@ diff --git a/approved/0005-coretime-interface.html b/approved/0005-coretime-interface.html index 1c2cb29..05879f8 100644 --- a/approved/0005-coretime-interface.html +++ b/approved/0005-coretime-interface.html @@ -90,7 +90,7 @@ diff --git a/approved/0007-system-collator-selection.html b/approved/0007-system-collator-selection.html index 4986be3..864079b 100644 --- a/approved/0007-system-collator-selection.html +++ b/approved/0007-system-collator-selection.html @@ -90,7 +90,7 @@ diff --git a/approved/0008-parachain-bootnodes-dht.html b/approved/0008-parachain-bootnodes-dht.html index 357d1e5..f139d91 100644 --- a/approved/0008-parachain-bootnodes-dht.html +++ b/approved/0008-parachain-bootnodes-dht.html @@ -90,7 +90,7 @@ diff --git a/approved/0012-process-for-adding-new-collectives.html b/approved/0012-process-for-adding-new-collectives.html index a7a6940..e850e93 100644 --- a/approved/0012-process-for-adding-new-collectives.html +++ b/approved/0012-process-for-adding-new-collectives.html @@ -90,7 +90,7 @@ diff --git a/approved/0014-improve-locking-mechanism-for-parachains.html b/approved/0014-improve-locking-mechanism-for-parachains.html index 027e999..39f90d7 100644 --- a/approved/0014-improve-locking-mechanism-for-parachains.html +++ b/approved/0014-improve-locking-mechanism-for-parachains.html @@ -90,7 +90,7 @@ diff --git a/approved/0022-adopt-encointer-runtime.html b/approved/0022-adopt-encointer-runtime.html index b3230ae..61ade41 100644 --- a/approved/0022-adopt-encointer-runtime.html +++ b/approved/0022-adopt-encointer-runtime.html @@ -90,7 +90,7 @@ diff --git a/approved/0032-minimal-relay.html b/approved/0032-minimal-relay.html index aa20315..5d070f2 100644 --- a/approved/0032-minimal-relay.html +++ b/approved/0032-minimal-relay.html @@ -90,7 +90,7 @@ diff --git a/approved/0050-fellowship-salaries.html b/approved/0050-fellowship-salaries.html index c9fb979..d6ea1f1 100644 --- a/approved/0050-fellowship-salaries.html +++ b/approved/0050-fellowship-salaries.html @@ -90,7 +90,7 @@ diff --git a/approved/0056-one-transaction-per-notification.html b/approved/0056-one-transaction-per-notification.html index 899280e..e848857 100644 --- a/approved/0056-one-transaction-per-notification.html +++ b/approved/0056-one-transaction-per-notification.html @@ -90,7 +90,7 @@ @@ -271,7 +271,7 @@ This is equivalent to forcing the Vec<Transaction> to always - @@ -285,7 +285,7 @@ This is equivalent to forcing the Vec<Transaction> to always - diff --git a/index.html b/index.html index 4d67879..a62133f 100644 --- a/index.html +++ b/index.html @@ -90,7 +90,7 @@ diff --git a/introduction.html b/introduction.html index 4d67879..a62133f 100644 --- a/introduction.html +++ b/introduction.html @@ -90,7 +90,7 @@ diff --git a/print.html b/print.html index 24a81b8..f41e8ef 100644 --- a/print.html +++ b/print.html @@ -91,7 +91,7 @@ @@ -1902,294 +1902,47 @@ This is equivalent to forcing the Vec<Transaction> to always

None.

None. This is a simple isolated change.

-

(source)

-

Table of Contents

- -

RFC-0004: Remove the host-side runtime memory allocator

-
- - - -
Start Date2023-07-04
DescriptionUpdate the runtime-host interface to no longer make use of a host-side allocator
AuthorsPierre Krieger
-
-

Summary

-

Update the runtime-host interface to no longer make use of a host-side allocator.

-

Motivation

-

The heap allocation of the runtime is currently controlled by the host using a memory allocator on the host side.

-

The API of many host functions consists in allocating a buffer. For example, when calling ext_hashing_twox_256_version_1, the host allocates a 32 bytes buffer using the host allocator, and returns a pointer to this buffer to the runtime. The runtime later has to call ext_allocator_free_version_1 on this pointer in order to free the buffer.

-

Even though no benchmark has been done, it is pretty obvious that this design is very inefficient. To continue with the example of ext_hashing_twox_256_version_1, it would be more efficient to instead write the output hash to a buffer that was allocated by the runtime on its stack and passed by pointer to the function. Allocating a buffer on the stack in the worst case scenario simply consists in decreasing a number, and in the best case scenario is free. Doing so would save many Wasm memory reads and writes by the allocator, and would save a function call to ext_allocator_free_version_1.

-

Furthermore, the existence of the host-side allocator has become questionable over time. It is implemented in a very naive way, and for determinism and backwards compatibility reasons it needs to be implemented exactly identically in every client implementation. Runtimes make substantial use of heap memory allocations, and each allocation needs to go twice through the runtime <-> host boundary (once for allocating and once for freeing). Moving the allocator to the runtime side, while it would increase the size of the runtime, would be a good idea. But before the host-side allocator can be deprecated, all the host functions that make use of it need to be updated to not use it.

-

Stakeholders

-

No attempt was made at convincing stakeholders.

-

Explanation

-

New host functions

-

This section contains a list of new host functions to introduce.

-
(func $ext_storage_read_version_2
-    (param $key i64) (param $value_out i64) (param $offset i32) (result i64))
-(func $ext_default_child_storage_read_version_2
-    (param $child_storage_key i64) (param $key i64) (param $value_out i64)
-    (param $offset i32) (result i64))
-
-

The signature and behaviour of ext_storage_read_version_2 and ext_default_child_storage_read_version_2 is identical to their version 1 counterparts, but the return value has a different meaning. -The new functions directly return the number of bytes that were written in the value_out buffer. If the entry doesn't exist, a value of -1 is returned. Given that the host must never write more bytes than the size of the buffer in value_out, and that the size of this buffer is expressed as a 32 bits number, a 64bits value of -1 is not ambiguous.

-

The runtime execution stops with an error if value_out is outside of the range of the memory of the virtual machine, even if the size of the buffer is 0 or if the amount of data to write would be 0 bytes.

-
(func $ext_storage_next_key_version_2
-    (param $key i64) (param $out i64) (return i32))
-(func $ext_default_child_storage_next_key_version_2
-    (param $child_storage_key i64) (param $key i64) (param $out i64) (return i32))
-
-

The behaviour of these functions is identical to their version 1 counterparts. -Instead of allocating a buffer, writing the next key to it, and returning a pointer to it, the new version of these functions accepts an out parameter containing a pointer-size to the memory location where the host writes the output. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine, even if the function wouldn't write anything to out. -These functions return the size, in bytes, of the next key, or 0 if there is no next key. If the size of the next key is larger than the buffer in out, the bytes of the key that fit the buffer are written to out and any extra byte that doesn't fit is discarded.

-

Some notes:

- -
(func $ext_hashing_keccak_256_version_2
-    (param $data i64) (param $out i32))
-(func $ext_hashing_keccak_512_version_2
-    (param $data i64) (param $out i32))
-(func $ext_hashing_sha2_256_version_2
-    (param $data i64) (param $out i32))
-(func $ext_hashing_blake2_128_version_2
-    (param $data i64) (param $out i32))
-(func $ext_hashing_blake2_256_version_2
-    (param $data i64) (param $out i32))
-(func $ext_hashing_twox_64_version_2
-    (param $data i64) (param $out i32))
-(func $ext_hashing_twox_128_version_2
-    (param $data i64) (param $out i32))
-(func $ext_hashing_twox_256_version_2
-    (param $data i64) (param $out i32))
-(func $ext_trie_blake2_256_root_version_3
-    (param $data i64) (param $version i32) (param $out i32))
-(func $ext_trie_blake2_256_ordered_root_version_3
-    (param $data i64) (param $version i32) (param $out i32))
-(func $ext_trie_keccak_256_root_version_3
-    (param $data i64) (param $version i32) (param $out i32))
-(func $ext_trie_keccak_256_ordered_root_version_3
-    (param $data i64) (param $version i32) (param $out i32))
-(func $ext_default_child_storage_root_version_3
-    (param $child_storage_key i64) (param $out i32))
-(func $ext_crypto_ed25519_generate_version_2
-    (param $key_type_id i32) (param $seed i64) (param $out i32))
-(func $ext_crypto_sr25519_generate_version_2
-    (param $key_type_id i32) (param $seed i64) (param $out i32) (return i32))
-(func $ext_crypto_ecdsa_generate_version_2
-    (param $key_type_id i32) (param $seed i64) (param $out i32) (return i32))
-
-

The behaviour of these functions is identical to their version 1 or version 2 counterparts. Instead of allocating a buffer, writing the output to it, and returning a pointer to it, the new version of these functions accepts an out parameter containing the memory location where the host writes the output. The output is always of a size known at compilation time. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine.

-
(func $ext_default_child_storage_root_version_3
-    (param $child_storage_key i64) (param $out i32))
-(func $ext_storage_root_version_3
-    (param $out i32))
-
-

The behaviour of these functions is identical to their version 1 and version 2 counterparts. Instead of allocating a buffer, writing the output to it, and returning a pointer to it, the new versions of these functions accepts an out parameter containing the memory location where the host writes the output. The output is always of a size known at compilation time. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine.

-

I have taken the liberty to take the version 1 of these functions as a base rather than the version 2, as a PPP deprecating the version 2 of these functions has previously been accepted: https://github.com/w3f/PPPs/pull/6.

-
(func $ext_storage_clear_prefix_version_3
-    (param $prefix i64) (param $limit i64) (param $removed_count_out i32)
-    (return i32))
-(func $ext_default_child_storage_clear_prefix_version_3
-    (param $child_storage_key i64) (param $prefix i64)
-    (param $limit i64)  (param $removed_count_out i32) (return i32))
-(func $ext_default_child_storage_kill_version_4
-    (param $child_storage_key i64) (param $limit i64)
-    (param $removed_count_out i32) (return i32))
-
-

The behaviour of these functions is identical to their version 2 and 3 counterparts. Instead of allocating a buffer, writing the output to it, and returning a pointer to it, the version 3 and 4 of these functions accepts a removed_count_out parameter containing the memory location to a 8 bytes buffer where the host writes the number of keys that were removed in little endian. The runtime execution stops with an error if removed_count_out is outside of the range of the memory of the virtual machine. The functions return 1 to indicate that there are keys remaining, and 0 to indicate that all keys have been removed.

-

Note that there is an alternative proposal to add new host functions with the same names: https://github.com/w3f/PPPs/pull/7. This alternative doesn't conflict with this one except for the version number. One proposal or the other will have to use versions 4 and 5 rather than 3 and 4.

-
(func $ext_crypto_ed25519_sign_version_2
-    (param $key_type_id i32) (param $key i32) (param $msg i64) (param $out i32) (return i32))
-(func $ext_crypto_sr25519_sign_version_2
-    (param $key_type_id i32) (param $key i32) (param $msg i64) (param $out i32) (return i32))
-func $ext_crypto_ecdsa_sign_version_2
-    (param $key_type_id i32) (param $key i32) (param $msg i64) (param $out i32) (return i32))
-(func $ext_crypto_ecdsa_sign_prehashed_version_2
-    (param $key_type_id i32) (param $key i32) (param $msg i64) (param $out i32) (return i64))
-
-

The behaviour of these functions is identical to their version 1 counterparts. The new versions of these functions accept an out parameter containing the memory location where the host writes the signature. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine, even if the function wouldn't write anything to out. The signatures are always of a size known at compilation time. On success, these functions return 0. If the public key can't be found in the keystore, these functions return 1 and do not write anything to out.

-

Note that the return value is 0 on success and 1 on failure, while the previous version of these functions write 1 on success (as it represents a SCALE-encoded Some) and 0 on failure (as it represents a SCALE-encoded None). Returning 0 on success and non-zero on failure is consistent with common practices in the C programming language and is less surprising than the opposite.

-
(func $ext_crypto_secp256k1_ecdsa_recover_version_3
-    (param $sig i32) (param $msg i32) (param $out i32) (return i64))
-(func $ext_crypto_secp256k1_ecdsa_recover_compressed_version_3
-    (param $sig i32) (param $msg i32) (param $out i32) (return i64))
-
-

The behaviour of these functions is identical to their version 2 counterparts. The new versions of these functions accept an out parameter containing the memory location where the host writes the signature. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine, even if the function wouldn't write anything to out. The signatures are always of a size known at compilation time. On success, these functions return 0. On failure, these functions return a non-zero value and do not write anything to out.

-

The non-zero value written on failure is:

- -

These values are equal to the values returned on error by the version 2 (see https://spec.polkadot.network/chap-host-api#defn-ecdsa-verify-error), but incremented by 1 in order to reserve 0 for success.

-
(func $ext_crypto_ed25519_num_public_keys_version_1
-    (param $key_type_id i32) (return i32))
-(func $ext_crypto_ed25519_public_key_version_2
-    (param $key_type_id i32) (param $key_index i32) (param $out i32))
-(func $ext_crypto_sr25519_num_public_keys_version_1
-    (param $key_type_id i32) (return i32))
-(func $ext_crypto_sr25519_public_key_version_2
-    (param $key_type_id i32) (param $key_index i32) (param $out i32))
-(func $ext_crypto_ecdsa_num_public_keys_version_1
-    (param $key_type_id i32) (return i32))
-(func $ext_crypto_ecdsa_public_key_version_2
-    (param $key_type_id i32) (param $key_index i32) (param $out i32))
-
-

The functions superceded the ext_crypto_ed25519_public_key_version_1, ext_crypto_sr25519_public_key_version_1, and ext_crypto_ecdsa_public_key_version_1 host functions.

-

Instead of calling ext_crypto_ed25519_public_key_version_1 in order to obtain the list of all keys at once, the runtime should instead call ext_crypto_ed25519_num_public_keys_version_1 in order to obtain the number of public keys available, then ext_crypto_ed25519_public_key_version_2 repeatedly. -The ext_crypto_ed25519_public_key_version_2 function writes the public key of the given key_index to the memory location designated by out. The key_index must be between 0 (included) and n (excluded), where n is the value returned by ext_crypto_ed25519_num_public_keys_version_1. Execution must trap if n is out of range.

-

The same explanations apply for ext_crypto_sr25519_public_key_version_1 and ext_crypto_ecdsa_public_key_version_1.

-

Host implementers should be aware that the list of public keys (including their ordering) must not change while the runtime is running. This is most likely done by copying the list of all available keys either at the start of the execution or the first time the list is accessed.

-
(func $ext_offchain_http_request_start_version_2
-  (param $method i64) (param $uri i64) (param $meta i64) (result i32))
-
-

The behaviour of this function is identical to its version 1 counterpart. Instead of allocating a buffer, writing the request identifier in it, and returning a pointer to it, the version 2 of this function simply returns the newly-assigned identifier to the HTTP request. On failure, this function returns -1. An identifier of -1 is invalid and is reserved to indicate failure.

-
(func $ext_offchain_http_request_write_body_version_2
-  (param $method i64) (param $uri i64) (param $meta i64) (result i32))
-(func $ext_offchain_http_response_read_body_version_2
-  (param $request_id i32) (param $buffer i64) (param $deadline i64) (result i64))
-
-

The behaviour of these functions is identical to their version 1 counterpart. Instead of allocating a buffer, writing two bytes in it, and returning a pointer to it, the new version of these functions simply indicates what happened:

- -

These values are equal to the values returned on error by the version 1 (see https://spec.polkadot.network/chap-host-api#defn-http-error), but tweaked in order to reserve positive numbers for success.

-

When it comes to ext_offchain_http_response_read_body_version_2, the host implementers must not read too much data at once in order to not create ambiguity in the returned value. Given that the size of the buffer is always inferior or equal to 4 GiB, this is not a problem.

-
(func $ext_offchain_http_response_wait_version_2
-    (param $ids i64) (param $deadline i64) (param $out i32))
-
-

The behaviour of this function is identical to its version 1 counterpart. Instead of allocating a buffer, writing the output to it, and returning a pointer to it, the new version of this function accepts an out parameter containing the memory location where the host writes the output. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine.

-

The encoding of the response code is also modified compared to its version 1 counterpart and each response code now encodes to 4 little endian bytes as described below:

- -

The buffer passed to out must always have a size of 4 * n where n is the number of elements in the ids.

-
(func $ext_offchain_http_response_header_name_version_1
-    (param $request_id i32) (param $header_index i32) (param $out i64) (result i64))
-(func $ext_offchain_http_response_header_value_version_1
-    (param $request_id i32) (param $header_index i32) (param $out i64) (result i64))
-
-

These functions supercede the ext_offchain_http_response_headers_version_1 host function.

-

Contrary to ext_offchain_http_response_headers_version_1, only one header indicated by header_index can be read at a time. Instead of calling ext_offchain_http_response_headers_version_1 once, the runtime should call ext_offchain_http_response_header_name_version_1 and ext_offchain_http_response_header_value_version_1 multiple times with an increasing header_index, until a value of -1 is returned.

-

These functions accept an out parameter containing a pointer-size to the memory location where the header name or value should be written. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine, even if the function wouldn't write anything to out.

-

These functions return the size, in bytes, of the header name or header value. If request doesn't exist or is in an invalid state (as documented for ext_offchain_http_response_headers_version_1) or the header_index is out of range, a value of -1 is returned. Given that the host must never write more bytes than the size of the buffer in out, and that the size of this buffer is expressed as a 32 bits number, a 64bits value of -1 is not ambiguous.

-

If the buffer in out is too small to fit the entire header name of value, only the bytes that fit are written and the rest are discarded.

-
(func $ext_offchain_submit_transaction_version_2
-    (param $data i64) (return i32))
-(func $ext_offchain_http_request_add_header_version_2
-    (param $request_id i32) (param $name i64) (param $value i64) (result i32))
-
-

Instead of allocating a buffer, writing 1 or 0 in it, and returning a pointer to it, the version 2 of these functions return 0 or 1, where 0 indicates success and 1 indicates failure. The runtime must interpret any non-0 value as failure, but the client must always return 1 in case of failure.

-
(func $ext_offchain_local_storage_read_version_1
-    (param $kind i32) (param $key i64) (param $value_out i64) (param $offset i32) (result i64))
-
-

This function supercedes the ext_offchain_local_storage_get_version_1 host function, and uses an API and logic similar to ext_storage_read_version_2.

-

It reads the offchain local storage key indicated by kind and key starting at the byte indicated by offset, and writes the value to the pointer-size indicated by value_out.

-

The function returns the number of bytes that were written in the value_out buffer. If the entry doesn't exist, a value of -1 is returned. Given that the host must never write more bytes than the size of the buffer in value_out, and that the size of this buffer is expressed as a 32 bits number, a 64bits value of -1 is not ambiguous.

-

The runtime execution stops with an error if value_out is outside of the range of the memory of the virtual machine, even if the size of the buffer is 0 or if the amount of data to write would be 0 bytes.

-
(func $ext_offchain_network_peer_id_version_1
-    (param $out i64))
-
-

This function writes the PeerId of the local node to the memory location indicated by out. A PeerId is always 38 bytes long. -The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine.

-
(func $ext_input_size_version_1
-    (return i64))
-(func $ext_input_read_version_1
-    (param $offset i64) (param $out i64))
-
-

When a runtime function is called, the host uses the allocator to allocate memory within the runtime where to write some input data. These two new host functions provide an alternative way to access the input that doesn't make use of the allocator.

-

The ext_input_size_version_1 host function returns the size in bytes of the input data.

-

The ext_input_read_version_1 host function copies some data from the input data to the memory of the runtime. The offset parameter indicates the offset within the input data where to start copying, and must be inferior or equal to the value returned by ext_input_size_version_1. The out parameter is a pointer-size containing the buffer where to write to. -The runtime execution stops with an error if offset is strictly superior to the size of the input data, or if out is outside of the range of the memory of the virtual machine, even if the amount of data to copy would be 0 bytes.

-

Other changes

-

In addition to the new host functions, this RFC proposes two changes to the runtime-host interface:

- -

All the host functions that are being superceded by new host functions are now considered deprecated and should no longer be used. -The following other host functions are similarly also considered deprecated:

- -

Drawbacks

-

This RFC might be difficult to implement in Substrate due to the internal code design. It is not clear to the author of this RFC how difficult it would be.

-

Prior Art

-

The API of these new functions was heavily inspired by API used by the C programming language.

-

Unresolved Questions

-

The changes in this RFC would need to be benchmarked. This involves implementing the RFC and measuring the speed difference.

-

It is expected that most host functions are faster or equal speed to their deprecated counterparts, with the following exceptions:

- -

Future Possibilities

-

After this RFC, we can remove from the source code of the host the allocator altogether in a future version, by removing support for all the deprecated host functions. -This would remove the possibility to synchronize older blocks, which is probably controversial and requires a some preparations that are out of scope of this RFC.

(source)

Table of Contents

@@ -2200,16 +1953,16 @@ This would remove the possibility to synchronize older blocks, which is probably AuthorsAurora Poppyseed, Just_Luuuu, Viki Val -

Summary

-

This RFC proposes changing the current deposit requirements on the Polkadot and Kusama Asset Hub for creating NFT collections. The objective is to lower the barrier to entry for artists, fostering a more inclusive and vibrant ecosystem while maintaining network integrity and preventing spam.

-

Motivation

-

The current deposit of 10 DOT for collection creation on the Polkadot Asset Hub presents a significant financial barrier for many artists. By lowering the deposit requirements, we aim to encourage more artists to participate in the Polkadot NFT ecosystem, thereby enriching the diversity and vibrancy of the community and its offerings.

+

Summary

+

This RFC proposes changing the current deposit requirements on the Polkadot and Kusama Asset Hub for creating NFT collection, minting an individual NFT, and lowering it's coresponding metadata and attribute deposit. The objective is to lower the barrier to entry for NFT creators, fostering a more inclusive and vibrant ecosystem while maintaining network integrity and preventing spam.

+

Motivation

+

The current deposit of 10 DOT for collection creation (along with 0.01 DOT for item deposit and 0.2 DOT for metadata and attribute deposit) on the Polkadot Asset Hub and 0.1 KSM on Kusama Asset Hub presents a significant financial barrier for many NFT creators. By lowering the deposit requirements, we aim to encourage more NFT creators to participate in the Polkadot NFT ecosystem, thereby enriching the diversity and vibrancy of the community and its offerings.

The actual implementation of the deposit is an arbitrary number coming from Uniques pallet. It is not a result of any economic analysis. This proposal aims to adjust the deposit from constant to dynamic pricing based on the deposit function with respect to stakeholders.

Requirements

-

Stakeholders

+

Stakeholders

Previous discussions have been held within the Polkadot Forum community and with artists expressing their concerns about the deposit amounts. Link.

-

Explanation

+

Explanation

+

This RFC proposes a revision of the deposit constants in the nfts pallet on the Polkadot Asset Hub. The new deposit amounts would be determined by a standard deposit formula.

This RFC suggests modifying deposit constants defined in the nfts pallet on the Polkadot Asset Hub to require a lower deposit. The reduced deposit amount should be determined by the deposit adjusted by the pricing mechanism (arbitrary number/another pricing function).

-

Current deposit requirements are as follows:

+

Current code structure

+

Current deposit requirements are as follows

+

Looking at the current code structure the currently implemented we can find that the pricing re-uses the logic of how Uniques are defined:

#![allow(unused)]
 fn main() {
 parameter_types! {
@@ -2230,9 +1986,11 @@ This would remove the possibility to synchronize older blocks, which is probably
 	pub const NftsAttributeDepositBase: Balance = UniquesAttributeDepositBase::get();
 	pub const NftsDepositPerByte: Balance = UniquesDepositPerByte::get();
 }
-
-// 
-parameter_types! {
+}
+

In the existing setup, the Uniques are defined with specific deposit values for different elements:

+
#![allow(unused)]
+fn main() {
+parameter_types! {
 	pub const UniquesCollectionDeposit: Balance = UNITS / 10; // 1 / 10 UNIT deposit to create a collection
 	pub const UniquesItemDeposit: Balance = UNITS / 1_000; // 1 / 1000 UNIT deposit to mint an item
 	pub const UniquesMetadataDepositBase: Balance = deposit(1, 129);
@@ -2240,7 +1998,38 @@ parameter_types! {
 	pub const UniquesDepositPerByte: Balance = deposit(0, 1);
 }
 }
-

The proposed change would modify the deposit constants to require a lower deposit. The reduced deposit amount should be determined by deposit adjusted by an arbitrary number.

+

As we can see in the code definition above the current code does not use the deposit funtion when the collection in the following instances: UniquesCollectionDeposit and UniquesItemDeposit.

+

Proposed Modification Using the Deposit Function

+

This proposed modification adjusts the deposits to use the deposit function instead of using an arbitrary number.

+
#![allow(unused)]
+fn main() {
+parameter_types! {
+	pub const NftsCollectionDeposit: Balance = deposit(1, 130);
+	pub const NftsItemDeposit: Balance = deposit(1, 164);
+	pub const NftsMetadataDepositBase: Balance = deposit(1, 129);
+	pub const NftsAttributeDepositBase: Balance = deposit(1, 0);
+	pub const NftsDepositPerByte: Balance = deposit(0, 1);
+}
+}
+

Calculations viewed bellow were calculated by using the following repository rfc-pricing. +Polkadot +| Name | Current price implementation | Proposed Modified by using the new deposit function | +|---------------------------|----------------------------------|-------------------------| +| collectionDeposit | 10 DOT | 0.20064 DOT | +| itemDeposit | 0.01 DOT | 0.20081 DOT | +| metadataDepositBase | 0.20129 DOT | 0.20076 DOT | +| attributeDepositBase | 0.2 DOT | 0.2 DOT |

+

Similarly the prices for Kusama ecosystem were calculated as: +Kusama: +| Name | Current price implementation | Proposed Price in KSM | +|---------------------------|----------------------------------|---------------------------| +| collectionDeposit | 0.1 KSM | 0.006688 KSM | +| itemDeposit | 0.001 KSM | 0.000167 KSM | +| metadataDepositBase | 0.006709666617 KSM | 0.0006709666617 KSM | +| attributeDepositBase | 0.00666666666 KSM | 0.000666666666 KSM |

+

Enhanced Approach to Further Lower Barriers for Entry

+

In an effort to further lower barriers to entry and foster greater inclusivity, we propose additional modifications to the pricing structure. These proposed reductions are based on a collaborative and calculated approach, involving the consensus of leading NFT creators within the Polkadot and Kusama Asset Hub communities. The adjustments to deposit amounts are not made arbitrarily. Instead, they are the result of detailed discussions and analyses conducted with prominent NFT creators.

+

Proposed Code Adjustments

#![allow(unused)]
 fn main() {
 parameter_types! {
@@ -2251,68 +2040,76 @@ parameter_types! {
 	pub const NftsDepositPerByte: Balance = deposit(0, 1);
 }
 }
-

Prices and Proposed Prices on Polkadot Asset Hub: -Scroll right

-
| **Name**                  | **Current price implementation** | **Price if DOT = 5$**  | **Price if DOT goes to 50$**  | **Proposed Price in DOT** | **Proposed Price if DOT = 5$**   | **Proposed Price if DOT goes to 50$**|
-|---------------------------|----------------------------------|------------------------|-------------------------------|---------------------------|----------------------------------|--------------------------------------|
-| collectionDeposit         | 10 DOT                           | 50 $                   | 500 $                         | 0.20064 DOT                   | ~1 $                            | 10.32$                                   |
-| itemDeposit               | 0.01 DOT                         | 0.05 $                 | 0.5 $                         | 0.005 DOT                 | 0.025 $                          | 0.251$                                |
-| metadataDepositBase       | 0.20129 DOT                      | 1.00645 $              | 10.0645 $                     | 0.0020129 DOT             | 0.0100645 $                      | 0.100645$                            |
-| attributeDepositBase      | 0.2 DOT                          | 1 $                    | 10 $                          | 0.002 DOT                 | 0.01 $                           | 0.1$                                 |
-
-

Prices and Proposed Prices on Kusama Asset Hub: -Scroll right

-
| **Name**                  | **Current price implementation** | **Price if KSM = 23$** | **Price if KSM goes to 500$** | **Proposed Price in KSM** | **Proposed Price if KSM = 23$**  | **Proposed Price if KSM goes to 500$** |
-|---------------------------|----------------------------------|------------------------|-------------------------------|---------------------------|----------------------------------|----------------------------------------|
-| collectionDeposit         | 0.1 KSM                          | 2.3 $                  | 50 $                          | 0.006688 KSM                  | 0.154 $                           | 3.34 $                                    |
-| itemDeposit               | 0.001 KSM                        | 0.023 $                | 0.5 $                         | 0.000167 KSM                | 0.00385 $                         | 0.0835 $                                 |
-| metadataDepositBase       | 0.006709666617 KSM               | 0.15432183319 $        | 3.3548333085 $                | 0.0006709666617 KSM       | 0.015432183319 $                 | 0.33548333085 $                        |
-| attributeDepositBase      | 0.00666666666 KSM                | 0.15333333318 $        | 3.333333333 $                 | 0.000666666666 KSM        | 0.015333333318 $                 | 0.3333333333 $                         |
-
-
-
-

Note: This is only a proposal for change and can be modified upon additional conversation.

-
-

Drawbacks

+

Prices and Proposed Prices on Polkadot Asset Hub:

+

Polkadot +| Name | Current price implementation | Proposed Prices | +|---------------------------|----------------------------------|---------------------| +| collectionDeposit | 10 DOT | 0.20064 DOT | +| itemDeposit | 0.01 DOT | 0.005 DOT | +| metadataDepositBase | 0.20129 DOT | 0.002 DOT | +| attributeDepositBase | 0.2 DOT | 0.002 DOT |

+

Kusama +| Name | Current price implementation | Proposed Price in KSM | +|---------------------------|----------------------------------|---------------------------| +| collectionDeposit | 0.1 KSM | 0.006688 KSM | +| itemDeposit | 0.001 KSM | 0.000167 KSM | +| metadataDepositBase | 0.006709666617 KSM | 0.0006709666617 KSM | +| attributeDepositBase | 0.00666666666 KSM | 0.000666666666 KSM |

+

Discussion of Other Proposals

+

Several innovative proposals have been considered to enhance the network's adaptability and manage deposit requirements more effectively:

+

Enhanced Weak Governance Origin Model

+

The concept of a weak governance origin, controlled by a consortium like the System Collective, has been proposed. This model would allow for dynamic adjustments of NFT deposit requirements in response to market conditions, adhering to storage deposit norms.

+

Enhancements and Concerns:

+ +

Function-Based Pricing Model

+

Another proposal is to use a mathematical function to regulate deposit prices, initially allowing low prices to encourage participation, followed by a gradual increase to prevent network bloat.

+

Refinements:

+ +

Linking Deposit to USD(x) Value

+

This approach suggests pegging the deposit value to a stable currency like the USD, introducing predictability and stability for network users.

+

Considerations and Challenges:

+ +

Each of these proposals offers unique advantages and challenges. The optimal approach may involve a combination of these ideas, carefully adjusted to address the specific needs and dynamics of the Polkadot and Kusama networks.

+

Drawbacks

Modifying deposit requirements necessitates a balanced assessment of the potential drawbacks. Highlighted below are cogent points extracted from the discourse on the Polkadot Forum conversation, which provide critical perspectives on the implications of such changes:

-
-

But NFT deposits were chosen somewhat arbitrarily at genesis and it’s a good exercise to re-evaluate them and adapt if they are causing pain and if lowering them has little or no negative side effect (or if the trade-off is worth it). --> joepetrowski

-
-
-

Underestimates mean that state grows faster, although not unbounded - effectively an economic subsidy on activity. Overestimates mean that the state grows slower - effectively an economic depressant on activity. --> rphmeier

-
-
-

Technical: We want to prevent state bloat, therefore using state should have a cost associated with it. --> joepetrowski

-
+

The discourse around modifying deposit requirements includes various perspectives:

+

Adjusting NFT deposit requirements on Polkadot and Kusama Asset Hubs involves key challenges:

+
    +
  1. +

    State Growth and Technical Concerns: Lowering deposit requirements can lead to increased blockchain state size, potentially causing state bloat. This growth needs to be managed to prevent strain on the network's resources and maintain operational efficiency.

    +
  2. +
  3. +

    Network Security and Market Response: Reduced deposits might increase transaction volume, potentially bloating the state, thereby impacting network security. Additionally, adapting to the cryptocurrency market's volatility is crucial. The mechanism for setting deposit amounts must be responsive yet stable, avoiding undue complexity for users.

    +
  4. +
  5. +

    Economic Impact on Previous Stakeholders: The change could have varied economic effects on previous (before the change) creators, platform operators, and investors. Balancing these interests is essential to ensure the adjustment benefits the ecosystem without negatively impacting its value dynamics. However in the particular case of Polkadot and Kusama Asset Hub this does not pose a concern since there are very few collections currently and thus previous stakeholders wouldn't be much affected. As of date 9th January 2024 there are 42 collections on Polkadot Asset Hub and 191 on Kusama Asset Hub with a relatively low volume.

    +
  6. +

Testing, Security, and Privacy

-

The change is backwards compatible. The prevention of "spam" could be prevented by OpenGov proposal to forceDestoy list of collections that are not suitable.

+

Security concerns

+

The prevention of "spam" could be prevented by OpenGov proposal to forceDestoy list of collections that are not suitable.

Performance, Ergonomics, and Compatibility

Performance

-

This change is not expected to have a significant impact on the overall performance of the Polkadot Asset Hub. However, monitoring the network closely, especially in the initial stages after implementation, is crucial to identify and mitigate any potential issues.

-

Additionally, a supplementary proposal aims to augment the network's adaptability:

-
-

Just from a technical perspective; I think the best we can do is to use a weak governance origin that is controlled by some consortium (ie. System Collective). -This origin could then update the NFT deposits any time the market conditions warrant it - obviously while honoring the storage deposit requirements. -To implement this, we need RFC#12 and the Parameters pallet from @xlc. --> OliverTY

-
-

This dynamic governance approach would facilitate a responsive and agile economic model for deposit management, ensuring that the network remains accessible and robust in the face of market volatility.

+

The primary performance consideration stems from the potential for state bloat due to increased activity from lower deposit requirements. It's vital to monitor and manage this to avoid any negative impact on the chain's performance. Strategies for mitigating state bloat, including efficient data management and periodic reviews of storage requirements, will be essential.

Ergonomics

-

The proposed change aims to enhance the user experience for artists, making Polkadot more accessible and user-friendly.

+

The proposed change aims to enhance the user experience for artists, traders and utilizers of Kusama and Polkadot asset hub. Making Polkadot and Kusama more accessible and user-friendly.

Compatibility

The change does not impact compatibility as redeposit function is already implemented.

-

Unresolved Questions

- +

Unresolved Questions

+

There remain unresolved questions regarding the implementation of a function-based pricing model for deposits and the feasibility of linking deposits to a USD(x) value. These aspects require further exploration and discussion to ascertain their viability and potential impact on the ecosystem.

- -

If accepted, this RFC could pave the way for further discussions and proposals aimed at enhancing the inclusivity and accessibility of the Polkadot ecosystem. Future work could also explore having a weak governance origin for deposits as proposed by Oliver.

+

We recommend initially lowering the deposit to the suggested levels. Subsequently, based on the outcomes and feedback, we can continue discussions on more complex models such as function-based pricing or currency-linked deposits.

+

If accepted, this RFC could pave the way for further discussions and proposals aimed at enhancing the inclusivity and accessibility of the Polkadot ecosystem.

(source)

Table of Contents

-

Unresolved Questions

+

Unresolved Questions

Implementation details and overall code is still up to discussion.

(source)

Table of Contents

@@ -3435,13 +3232,13 @@ privacy-enhancing mechanisms to address this concern. AuthorsVedhavyas Singareddi -

Summary

+

Summary

At the moment, we have system_version field on RuntimeVersion that derives which state version is used for the Storage. We have a use case where we want extrinsics root is derived using StateVersion::V1. Without defining a new field under RuntimeVersion, we would like to propose adding system_version that can be used to derive both storage and extrinsic state version.

-

Motivation

+

Motivation

Since the extrinsic state version is always StateVersion::V0, deriving extrinsic root requires full extrinsic data. This would be problematic when we need to verify the extrinsics root if the extrinsic sizes are bigger. This problem is further explored in https://github.com/polkadot-fellows/RFCs/issues/19

@@ -3453,11 +3250,11 @@ One of the main challenge here is some extrinsics could be big enough that this included in the Consensus block due to Block's weight restriction. If the extrinsic root is derived using StateVersion::V1, then we do not need to pass the full extrinsic data but rather at maximum, 32 byte of extrinsic data.

-

Stakeholders

+

Stakeholders

-

Explanation

+

Explanation

In order to use project specific StateVersion for extrinsic roots, we proposed an implementation that introduced parameter to frame_system::Config but that unfortunately did not feel correct. @@ -3483,7 +3280,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { system_version: 1, }; } -

Drawbacks

+

Drawbacks

There should be no drawbacks as it would replace state_version with same behavior but documentation should be updated so that chains know which system_version to use.

Testing, Security, and Privacy

@@ -3500,7 +3297,7 @@ so that chains know which system_version to use.

We proposed introducing a similar change by introducing a parameter to frame_system::Config but did not feel that is the correct way of introducing this change.

-

Unresolved Questions

+

Unresolved Questions

I do not have any specific questions about this change at the moment.

IMO, this change is pretty self-contained and there won't be any future work necessary.

@@ -3543,9 +3340,9 @@ is the correct way of introducing this change.

AuthorsSergej Sakac -

Summary

+

Summary

This RFC proposes a new model for a sustainable on-demand parachain registration, involving a smaller initial deposit and periodic rent payments. The new model considers that on-demand chains may be unregistered and later re-registered. The proposed solution also ensures a quick startup for on-demand chains on Polkadot in such cases.

-

Motivation

+

Motivation

With the support of on-demand parachains on Polkadot, there is a need to explore a new, more cost-effective model for registering validation code. In the current model, the parachain manager is responsible for reserving a unique ParaId and covering the cost of storing the validation code of the parachain. These costs can escalate, particularly if the validation code is large. We need a better, sustainable model for registering on-demand parachains on Polkadot to help smaller teams deploy more easily.

This RFC suggests a new payment model to create a more financially viable approach to on-demand parachain registration. In this model, a lower initial deposit is required, followed by recurring payments upon parachain registration.

This new model will coexist with the existing one-time deposit payment model, offering teams seeking to deploy on-demand parachains on Polkadot a more cost-effective alternative.

@@ -3559,11 +3356,11 @@ is the correct way of introducing this change.

  • The solution MUST allow anyone to pay the rent.
  • The solution MUST prevent the removal of validation code if it could still be required for disputes or approval checking.
  • -

    Stakeholders

    +

    Stakeholders

    -

    Explanation

    +

    Explanation

    This RFC proposes a set of changes that will enable the new rent based approach to registering and storing validation code on-chain. The new model, compared to the current one, will require periodic rent payments. The parachain won't be pruned automatically if the rent is not paid, but by permitting anyone to prune the parachain and rewarding the caller, there will be an incentive for the removal of the validation code.

    On-demand parachains should still be able to utilize the current one-time payment model. However, given the size of the deposit required, it's highly likely that most on-demand parachains will opt for the new rent-based model.

    @@ -3670,7 +3467,7 @@ pub(super) type CheckedCodeHash<T: Config> = StorageMap<_, Twox64Concat, ParaId, ValidationCodeHash>; }

    To enable parachain re-registration, we should introduce a new extrinsic in the paras-registrar pallet that allows this. The logic of this extrinsic will be same as regular registration, with the distinction that it can be called by anyone, and the required deposit will be smaller since it only has to cover for the storage of the validation code.

    -

    Drawbacks

    +

    Drawbacks

    This RFC does not alter the process of reserving a ParaId, and therefore, it does not propose reducing it, even though such a reduction could be beneficial.

    Even though this RFC doesn't delve into the specifics of the configuration values for parachain registration but rather focuses on the mechanism, configuring it carelessly could lead to potential problems.

    Since the validation code hash and head data are not removed when the parachain is pruned but only when the deregister extrinsic is called, the T::DataDepositPerByte must be set to a higher value to create a strong enough incentive for removing it from the state.

    @@ -3688,7 +3485,7 @@ pub(super) type CheckedCodeHash<T: Config> =

    This RFC does not break compatibility.

    Prior Art and References

    Prior discussion on this topic: https://github.com/paritytech/polkadot-sdk/issues/1796

    -

    Unresolved Questions

    +

    Unresolved Questions

    None at this time.

    As noted in this GitHub issue, we want to raise the per-byte cost of on-chain data storage. However, a substantial increase in this cost would make it highly impractical for on-demand parachains to register on Polkadot. @@ -3747,9 +3544,9 @@ This RFC offers an alternative solution for on-demand parachains, ensuring that AuthorsAlzymologist Oy, Zondax LLC, Parity GmbH -

    Summary

    +

    Summary

    Add a metadata digest value (33-byte constant within fixed spec_version) to Signed Extensions to supplement signer party with proof of correct extrinsic interpretation. The digest value is generated once before release and is well-known and deterministic. The digest mechanism is designed to be modular and flexible. It also supports partial metadata transfer as needed by the signing party's extrinsic decoding mechanism. This considers signing devices potentially limited communication bandwidth and/or memory capacity.

    -

    Motivation

    +

    Motivation

    Background

    While all blockchain systems support (at least in some sense) offline signing used in air-gapped wallets and lightweight embedded devices, only few allow simultaneously complex upgradeable logic and full message decoding on the cold off-line signer side; Substrate is one of these heartening few, and therefore - we should build on this feature to greatly improve transaction security, and thus in general, network resilience.

    As a starting point, it is important to recognise that prudence and due care are naturally required. As we build further reliance on this feature we should be very careful to make sure it works correctly every time so as not to create false sense of security.

    @@ -3779,11 +3576,11 @@ This RFC offers an alternative solution for on-demand parachains, ensuring that
  • Chunks handling mechanism SHOULD support chunks being sent in any order without memory utilization overhead;
  • Unused enum variants MUST be stripped (this has great impact on transmitted metadata size; examples: era enum, enum with all calls for call batching).
  • -

    Stakeholders

    +

    Stakeholders

    All chain teams are stakeholders, as implementing this feature would require timely effort on their side and would impact compatibility with older tools.

    This feature is essential for all offline signer tools; many regular signing tools might make use of it. In general, this RFC greatly improves security of any network implementing it, as many governing keys are used with offline signers.

    Implementing this RFC would remove requirement to maintain metadata portals manually, as task of metadata verification would be effectively moved to consensus mechanism of the chain.

    -

    Explanation

    +

    Explanation

    Detailed description of metadata shortening and digest process is provided in metadata-shortener crate (see cargo doc --open and examples). Below are presented algorithms of the process.

    Definitions

    Metadata structure

    @@ -3920,7 +3717,7 @@ modularized_registry.sort(|a, b| { 0x02 - 0xFFreservedreserved for future use -

    Drawbacks

    +

    Drawbacks

    Increased transaction size

    A 1-byte increase in transaction size due to signed extension value. Digest is not included in transferred transaction, only in signing process.

    Transition overhead

    @@ -3937,7 +3734,7 @@ modularized_registry.sort(|a, b| {

    Proposal in this form is not compatible with older tools that do not implement proper MetadataV14 self-descriptive features; those would have to be upgraded to include a new signed extensions field.

    Prior Art and References

    This project was developed upon a Polkadot Treasury grant; relevant development links are located in metadata-offline-project repository.

    -

    Unresolved Questions

    +

    Unresolved Questions

    1. How would polkadot-js handle the transition?
    2. Where would non-rust tools like Ledger apps get shortened metadata content?
    3. @@ -3985,11 +3782,11 @@ modularized_registry.sort(|a, b| { AuthorsAlin Dima -

      Summary

      +

      Summary

      Propose a way of permuting the availability chunk indices assigned to validators, in the context of recovering available data from systematic chunks, with the purpose of fairly distributing network bandwidth usage.

      -

      Motivation

      +

      Motivation

      Currently, the ValidatorIndex is always identical to the ChunkIndex. Since the validator array is only shuffled once per session, naively using the ValidatorIndex as the ChunkIndex would pose an unreasonable stress on the first N/3 validators during an entire session, when favouring availability recovery from systematic chunks.

      @@ -3997,9 +3794,9 @@ validators during an entire session, when favouring availability recovery from s systematic availability chunks to different validators, based on the relay chain block and core. The main purpose is to ensure fair distribution of network bandwidth usage for availability recovery in general and in particular for systematic chunk holders.

      -

      Stakeholders

      +

      Stakeholders

      Relay chain node core developers.

      -

      Explanation

      +

      Explanation

      Systematic erasure codes

      An erasure coding algorithm is considered systematic if it preserves the original unencoded data as part of the resulting code. @@ -4062,7 +3859,6 @@ or governance call.

      pub fn get_chunk_index( n_validators: u32, validator_index: ValidatorIndex, - block_number: BlockNumber, core_index: CoreIndex ) -> ChunkIndex { let threshold = systematic_threshold(n_validators); // Roughly n_validators/3 @@ -4154,7 +3950,7 @@ struct (added in https://github.com/paritytech/polkadot-sdk/pull/2177Configuration::set_node_feature extrinsic. Once the feature is enabled and new configuration is live, the validator->chunk mapping ceases to be a 1:1 mapping and systematic recovery may begin.

      -

      Drawbacks

      +

      Drawbacks

      Detail-heavy explanation of the RFC, suitable for explanation to an implementer of the changeset. This should address corner cases in detail and provide justification behind decisions, and provide rationale for how the design meets the solution requirements.

      -

      Drawbacks

      +

      Drawbacks

      The allocator inside of the runtime will make code size bigger, but it's not obvious. The allocator inside of the runtime maybe slow down(or speed up) the runtime, still not obvious.

      We could ignore these drawbacks since they are not prominent. And the execution efficiency is highly decided by runtime developer. We could not prevent a poor efficiency if developer want to do it.

      @@ -4452,7 +4248,7 @@ For the first year, we SHALL disable the v1 by default, and enable it by default
    4. Move the allocator inside of the runtime
    5. Add new allocator design
    6. -

      Unresolved Questions

      +

      Unresolved Questions

      None at this time.

      The content discussed with RFC-0004 is basically orthogonal, but it could still be considered together, and it is preferred that this rfc be implmentented first.

      @@ -4487,17 +4283,17 @@ For the first year, we SHALL disable the v1 by default, and enable it by default AuthorsSourabh Niyogi -

      Summary

      +

      Summary

      This RFC proposes lowering the existential deposit requirements on Asset Hub for Polkadot by a factor of 25, from 0.1 DOT to .004 DOT. The objective is to lower the barrier to entry for asset minters to mint a new asset to the entire DOT token holder base, and make Asset Hub on Polkadot a place where everyone can do small asset conversions.

      -

      Motivation

      +

      Motivation

      The current Existential deposit is 0.1 DOT on Asset Hub for Polkadot. While this is not does not appear to be a significant financial barrier for most people (only $0.80), this value makes Asset Hub impractical for Asset Hub Minters, specifically for the case where the Asset Hub Minters wishes to mint a new asset for the entire community of DOT holders (e.g. 1.25MM DOT holders would cost 125K DOT @ $8 = $1MM).

      By lowering the existential deposit requirements from 0.1 DOT to 0.004 DOT, the cost of minting to the entire community of DOT holders goes from an unmanagable number [125K DOT, the value of several houses circa December 2023] down to a manageable number [5K DOT, the value of a car circa December 2023].

      -

      Stakeholders

      +

      Stakeholders

      -

      Explanation

      +

      Explanation

      The exact amount of the existential deposit (ED) is proposed to be 0.004 DOT based on

      +

      (source)

      +

      Table of Contents

      + +

      RFC-0004: Remove the host-side runtime memory allocator

      +
      + + + +
      Start Date2023-07-04
      DescriptionUpdate the runtime-host interface to no longer make use of a host-side allocator
      AuthorsPierre Krieger
      +
      +

      Summary

      +

      Update the runtime-host interface to no longer make use of a host-side allocator.

      +

      Motivation

      +

      The heap allocation of the runtime is currently controlled by the host using a memory allocator on the host side.

      +

      The API of many host functions consists in allocating a buffer. For example, when calling ext_hashing_twox_256_version_1, the host allocates a 32 bytes buffer using the host allocator, and returns a pointer to this buffer to the runtime. The runtime later has to call ext_allocator_free_version_1 on this pointer in order to free the buffer.

      +

      Even though no benchmark has been done, it is pretty obvious that this design is very inefficient. To continue with the example of ext_hashing_twox_256_version_1, it would be more efficient to instead write the output hash to a buffer that was allocated by the runtime on its stack and passed by pointer to the function. Allocating a buffer on the stack in the worst case scenario simply consists in decreasing a number, and in the best case scenario is free. Doing so would save many Wasm memory reads and writes by the allocator, and would save a function call to ext_allocator_free_version_1.

      +

      Furthermore, the existence of the host-side allocator has become questionable over time. It is implemented in a very naive way, and for determinism and backwards compatibility reasons it needs to be implemented exactly identically in every client implementation. Runtimes make substantial use of heap memory allocations, and each allocation needs to go twice through the runtime <-> host boundary (once for allocating and once for freeing). Moving the allocator to the runtime side, while it would increase the size of the runtime, would be a good idea. But before the host-side allocator can be deprecated, all the host functions that make use of it need to be updated to not use it.

      +

      Stakeholders

      +

      No attempt was made at convincing stakeholders.

      +

      Explanation

      +

      New host functions

      +

      This section contains a list of new host functions to introduce.

      +
      (func $ext_storage_read_version_2
      +    (param $key i64) (param $value_out i64) (param $offset i32) (result i64))
      +(func $ext_default_child_storage_read_version_2
      +    (param $child_storage_key i64) (param $key i64) (param $value_out i64)
      +    (param $offset i32) (result i64))
      +
      +

      The signature and behaviour of ext_storage_read_version_2 and ext_default_child_storage_read_version_2 is identical to their version 1 counterparts, but the return value has a different meaning. +The new functions directly return the number of bytes that were written in the value_out buffer. If the entry doesn't exist, a value of -1 is returned. Given that the host must never write more bytes than the size of the buffer in value_out, and that the size of this buffer is expressed as a 32 bits number, a 64bits value of -1 is not ambiguous.

      +

      The runtime execution stops with an error if value_out is outside of the range of the memory of the virtual machine, even if the size of the buffer is 0 or if the amount of data to write would be 0 bytes.

      +
      (func $ext_storage_next_key_version_2
      +    (param $key i64) (param $out i64) (return i32))
      +(func $ext_default_child_storage_next_key_version_2
      +    (param $child_storage_key i64) (param $key i64) (param $out i64) (return i32))
      +
      +

      The behaviour of these functions is identical to their version 1 counterparts. +Instead of allocating a buffer, writing the next key to it, and returning a pointer to it, the new version of these functions accepts an out parameter containing a pointer-size to the memory location where the host writes the output. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine, even if the function wouldn't write anything to out. +These functions return the size, in bytes, of the next key, or 0 if there is no next key. If the size of the next key is larger than the buffer in out, the bytes of the key that fit the buffer are written to out and any extra byte that doesn't fit is discarded.

      +

      Some notes:

      + +
      (func $ext_hashing_keccak_256_version_2
      +    (param $data i64) (param $out i32))
      +(func $ext_hashing_keccak_512_version_2
      +    (param $data i64) (param $out i32))
      +(func $ext_hashing_sha2_256_version_2
      +    (param $data i64) (param $out i32))
      +(func $ext_hashing_blake2_128_version_2
      +    (param $data i64) (param $out i32))
      +(func $ext_hashing_blake2_256_version_2
      +    (param $data i64) (param $out i32))
      +(func $ext_hashing_twox_64_version_2
      +    (param $data i64) (param $out i32))
      +(func $ext_hashing_twox_128_version_2
      +    (param $data i64) (param $out i32))
      +(func $ext_hashing_twox_256_version_2
      +    (param $data i64) (param $out i32))
      +(func $ext_trie_blake2_256_root_version_3
      +    (param $data i64) (param $version i32) (param $out i32))
      +(func $ext_trie_blake2_256_ordered_root_version_3
      +    (param $data i64) (param $version i32) (param $out i32))
      +(func $ext_trie_keccak_256_root_version_3
      +    (param $data i64) (param $version i32) (param $out i32))
      +(func $ext_trie_keccak_256_ordered_root_version_3
      +    (param $data i64) (param $version i32) (param $out i32))
      +(func $ext_default_child_storage_root_version_3
      +    (param $child_storage_key i64) (param $out i32))
      +(func $ext_crypto_ed25519_generate_version_2
      +    (param $key_type_id i32) (param $seed i64) (param $out i32))
      +(func $ext_crypto_sr25519_generate_version_2
      +    (param $key_type_id i32) (param $seed i64) (param $out i32) (return i32))
      +(func $ext_crypto_ecdsa_generate_version_2
      +    (param $key_type_id i32) (param $seed i64) (param $out i32) (return i32))
      +
      +

      The behaviour of these functions is identical to their version 1 or version 2 counterparts. Instead of allocating a buffer, writing the output to it, and returning a pointer to it, the new version of these functions accepts an out parameter containing the memory location where the host writes the output. The output is always of a size known at compilation time. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine.

      +
      (func $ext_default_child_storage_root_version_3
      +    (param $child_storage_key i64) (param $out i32))
      +(func $ext_storage_root_version_3
      +    (param $out i32))
      +
      +

      The behaviour of these functions is identical to their version 1 and version 2 counterparts. Instead of allocating a buffer, writing the output to it, and returning a pointer to it, the new versions of these functions accepts an out parameter containing the memory location where the host writes the output. The output is always of a size known at compilation time. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine.

      +

      I have taken the liberty to take the version 1 of these functions as a base rather than the version 2, as a PPP deprecating the version 2 of these functions has previously been accepted: https://github.com/w3f/PPPs/pull/6.

      +
      (func $ext_storage_clear_prefix_version_3
      +    (param $prefix i64) (param $limit i64) (param $removed_count_out i32)
      +    (return i32))
      +(func $ext_default_child_storage_clear_prefix_version_3
      +    (param $child_storage_key i64) (param $prefix i64)
      +    (param $limit i64)  (param $removed_count_out i32) (return i32))
      +(func $ext_default_child_storage_kill_version_4
      +    (param $child_storage_key i64) (param $limit i64)
      +    (param $removed_count_out i32) (return i32))
      +
      +

      The behaviour of these functions is identical to their version 2 and 3 counterparts. Instead of allocating a buffer, writing the output to it, and returning a pointer to it, the version 3 and 4 of these functions accepts a removed_count_out parameter containing the memory location to a 8 bytes buffer where the host writes the number of keys that were removed in little endian. The runtime execution stops with an error if removed_count_out is outside of the range of the memory of the virtual machine. The functions return 1 to indicate that there are keys remaining, and 0 to indicate that all keys have been removed.

      +

      Note that there is an alternative proposal to add new host functions with the same names: https://github.com/w3f/PPPs/pull/7. This alternative doesn't conflict with this one except for the version number. One proposal or the other will have to use versions 4 and 5 rather than 3 and 4.

      +
      (func $ext_crypto_ed25519_sign_version_2
      +    (param $key_type_id i32) (param $key i32) (param $msg i64) (param $out i32) (return i32))
      +(func $ext_crypto_sr25519_sign_version_2
      +    (param $key_type_id i32) (param $key i32) (param $msg i64) (param $out i32) (return i32))
      +func $ext_crypto_ecdsa_sign_version_2
      +    (param $key_type_id i32) (param $key i32) (param $msg i64) (param $out i32) (return i32))
      +(func $ext_crypto_ecdsa_sign_prehashed_version_2
      +    (param $key_type_id i32) (param $key i32) (param $msg i64) (param $out i32) (return i64))
      +
      +

      The behaviour of these functions is identical to their version 1 counterparts. The new versions of these functions accept an out parameter containing the memory location where the host writes the signature. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine, even if the function wouldn't write anything to out. The signatures are always of a size known at compilation time. On success, these functions return 0. If the public key can't be found in the keystore, these functions return 1 and do not write anything to out.

      +

      Note that the return value is 0 on success and 1 on failure, while the previous version of these functions write 1 on success (as it represents a SCALE-encoded Some) and 0 on failure (as it represents a SCALE-encoded None). Returning 0 on success and non-zero on failure is consistent with common practices in the C programming language and is less surprising than the opposite.

      +
      (func $ext_crypto_secp256k1_ecdsa_recover_version_3
      +    (param $sig i32) (param $msg i32) (param $out i32) (return i64))
      +(func $ext_crypto_secp256k1_ecdsa_recover_compressed_version_3
      +    (param $sig i32) (param $msg i32) (param $out i32) (return i64))
      +
      +

      The behaviour of these functions is identical to their version 2 counterparts. The new versions of these functions accept an out parameter containing the memory location where the host writes the signature. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine, even if the function wouldn't write anything to out. The signatures are always of a size known at compilation time. On success, these functions return 0. On failure, these functions return a non-zero value and do not write anything to out.

      +

      The non-zero value written on failure is:

      + +

      These values are equal to the values returned on error by the version 2 (see https://spec.polkadot.network/chap-host-api#defn-ecdsa-verify-error), but incremented by 1 in order to reserve 0 for success.

      +
      (func $ext_crypto_ed25519_num_public_keys_version_1
      +    (param $key_type_id i32) (return i32))
      +(func $ext_crypto_ed25519_public_key_version_2
      +    (param $key_type_id i32) (param $key_index i32) (param $out i32))
      +(func $ext_crypto_sr25519_num_public_keys_version_1
      +    (param $key_type_id i32) (return i32))
      +(func $ext_crypto_sr25519_public_key_version_2
      +    (param $key_type_id i32) (param $key_index i32) (param $out i32))
      +(func $ext_crypto_ecdsa_num_public_keys_version_1
      +    (param $key_type_id i32) (return i32))
      +(func $ext_crypto_ecdsa_public_key_version_2
      +    (param $key_type_id i32) (param $key_index i32) (param $out i32))
      +
      +

      The functions superceded the ext_crypto_ed25519_public_key_version_1, ext_crypto_sr25519_public_key_version_1, and ext_crypto_ecdsa_public_key_version_1 host functions.

      +

      Instead of calling ext_crypto_ed25519_public_key_version_1 in order to obtain the list of all keys at once, the runtime should instead call ext_crypto_ed25519_num_public_keys_version_1 in order to obtain the number of public keys available, then ext_crypto_ed25519_public_key_version_2 repeatedly. +The ext_crypto_ed25519_public_key_version_2 function writes the public key of the given key_index to the memory location designated by out. The key_index must be between 0 (included) and n (excluded), where n is the value returned by ext_crypto_ed25519_num_public_keys_version_1. Execution must trap if n is out of range.

      +

      The same explanations apply for ext_crypto_sr25519_public_key_version_1 and ext_crypto_ecdsa_public_key_version_1.

      +

      Host implementers should be aware that the list of public keys (including their ordering) must not change while the runtime is running. This is most likely done by copying the list of all available keys either at the start of the execution or the first time the list is accessed.

      +
      (func $ext_offchain_http_request_start_version_2
      +  (param $method i64) (param $uri i64) (param $meta i64) (result i32))
      +
      +

      The behaviour of this function is identical to its version 1 counterpart. Instead of allocating a buffer, writing the request identifier in it, and returning a pointer to it, the version 2 of this function simply returns the newly-assigned identifier to the HTTP request. On failure, this function returns -1. An identifier of -1 is invalid and is reserved to indicate failure.

      +
      (func $ext_offchain_http_request_write_body_version_2
      +  (param $method i64) (param $uri i64) (param $meta i64) (result i32))
      +(func $ext_offchain_http_response_read_body_version_2
      +  (param $request_id i32) (param $buffer i64) (param $deadline i64) (result i64))
      +
      +

      The behaviour of these functions is identical to their version 1 counterpart. Instead of allocating a buffer, writing two bytes in it, and returning a pointer to it, the new version of these functions simply indicates what happened:

      + +

      These values are equal to the values returned on error by the version 1 (see https://spec.polkadot.network/chap-host-api#defn-http-error), but tweaked in order to reserve positive numbers for success.

      +

      When it comes to ext_offchain_http_response_read_body_version_2, the host implementers must not read too much data at once in order to not create ambiguity in the returned value. Given that the size of the buffer is always inferior or equal to 4 GiB, this is not a problem.

      +
      (func $ext_offchain_http_response_wait_version_2
      +    (param $ids i64) (param $deadline i64) (param $out i32))
      +
      +

      The behaviour of this function is identical to its version 1 counterpart. Instead of allocating a buffer, writing the output to it, and returning a pointer to it, the new version of this function accepts an out parameter containing the memory location where the host writes the output. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine.

      +

      The encoding of the response code is also modified compared to its version 1 counterpart and each response code now encodes to 4 little endian bytes as described below:

      + +

      The buffer passed to out must always have a size of 4 * n where n is the number of elements in the ids.

      +
      (func $ext_offchain_http_response_header_name_version_1
      +    (param $request_id i32) (param $header_index i32) (param $out i64) (result i64))
      +(func $ext_offchain_http_response_header_value_version_1
      +    (param $request_id i32) (param $header_index i32) (param $out i64) (result i64))
      +
      +

      These functions supercede the ext_offchain_http_response_headers_version_1 host function.

      +

      Contrary to ext_offchain_http_response_headers_version_1, only one header indicated by header_index can be read at a time. Instead of calling ext_offchain_http_response_headers_version_1 once, the runtime should call ext_offchain_http_response_header_name_version_1 and ext_offchain_http_response_header_value_version_1 multiple times with an increasing header_index, until a value of -1 is returned.

      +

      These functions accept an out parameter containing a pointer-size to the memory location where the header name or value should be written. The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine, even if the function wouldn't write anything to out.

      +

      These functions return the size, in bytes, of the header name or header value. If request doesn't exist or is in an invalid state (as documented for ext_offchain_http_response_headers_version_1) or the header_index is out of range, a value of -1 is returned. Given that the host must never write more bytes than the size of the buffer in out, and that the size of this buffer is expressed as a 32 bits number, a 64bits value of -1 is not ambiguous.

      +

      If the buffer in out is too small to fit the entire header name of value, only the bytes that fit are written and the rest are discarded.

      +
      (func $ext_offchain_submit_transaction_version_2
      +    (param $data i64) (return i32))
      +(func $ext_offchain_http_request_add_header_version_2
      +    (param $request_id i32) (param $name i64) (param $value i64) (result i32))
      +
      +

      Instead of allocating a buffer, writing 1 or 0 in it, and returning a pointer to it, the version 2 of these functions return 0 or 1, where 0 indicates success and 1 indicates failure. The runtime must interpret any non-0 value as failure, but the client must always return 1 in case of failure.

      +
      (func $ext_offchain_local_storage_read_version_1
      +    (param $kind i32) (param $key i64) (param $value_out i64) (param $offset i32) (result i64))
      +
      +

      This function supercedes the ext_offchain_local_storage_get_version_1 host function, and uses an API and logic similar to ext_storage_read_version_2.

      +

      It reads the offchain local storage key indicated by kind and key starting at the byte indicated by offset, and writes the value to the pointer-size indicated by value_out.

      +

      The function returns the number of bytes that were written in the value_out buffer. If the entry doesn't exist, a value of -1 is returned. Given that the host must never write more bytes than the size of the buffer in value_out, and that the size of this buffer is expressed as a 32 bits number, a 64bits value of -1 is not ambiguous.

      +

      The runtime execution stops with an error if value_out is outside of the range of the memory of the virtual machine, even if the size of the buffer is 0 or if the amount of data to write would be 0 bytes.

      +
      (func $ext_offchain_network_peer_id_version_1
      +    (param $out i64))
      +
      +

      This function writes the PeerId of the local node to the memory location indicated by out. A PeerId is always 38 bytes long. +The runtime execution stops with an error if out is outside of the range of the memory of the virtual machine.

      +
      (func $ext_input_size_version_1
      +    (return i64))
      +(func $ext_input_read_version_1
      +    (param $offset i64) (param $out i64))
      +
      +

      When a runtime function is called, the host uses the allocator to allocate memory within the runtime where to write some input data. These two new host functions provide an alternative way to access the input that doesn't make use of the allocator.

      +

      The ext_input_size_version_1 host function returns the size in bytes of the input data.

      +

      The ext_input_read_version_1 host function copies some data from the input data to the memory of the runtime. The offset parameter indicates the offset within the input data where to start copying, and must be inferior or equal to the value returned by ext_input_size_version_1. The out parameter is a pointer-size containing the buffer where to write to. +The runtime execution stops with an error if offset is strictly superior to the size of the input data, or if out is outside of the range of the memory of the virtual machine, even if the amount of data to copy would be 0 bytes.

      +

      Other changes

      +

      In addition to the new host functions, this RFC proposes two changes to the runtime-host interface:

      + +

      All the host functions that are being superceded by new host functions are now considered deprecated and should no longer be used. +The following other host functions are similarly also considered deprecated:

      + +

      Drawbacks

      +

      This RFC might be difficult to implement in Substrate due to the internal code design. It is not clear to the author of this RFC how difficult it would be.

      +

      Prior Art

      +

      The API of these new functions was heavily inspired by API used by the C programming language.

      +

      Unresolved Questions

      +

      The changes in this RFC would need to be benchmarked. This involves implementing the RFC and measuring the speed difference.

      +

      It is expected that most host functions are faster or equal speed to their deprecated counterparts, with the following exceptions:

      + +

      Future Possibilities

      +

      After this RFC, we can remove from the source code of the host the allocator altogether in a future version, by removing support for all the deprecated host functions. +This would remove the possibility to synchronize older blocks, which is probably controversial and requires a some preparations that are out of scope of this RFC.

      (source)

      Table of Contents

    7. Stakeholders
    8. -
    9. Explanation
    10. +
    11. Explanation + +
    12. +
    13. Discussion of Other Proposals + +
    14. Drawbacks
    15. -
    16. Testing, Security, and Privacy
    17. +
    18. Testing, Security, and Privacy + +
    19. Performance, Ergonomics, and Compatibility
      • Performance
      • @@ -209,9 +226,9 @@

        Summary

        -

        This RFC proposes changing the current deposit requirements on the Polkadot and Kusama Asset Hub for creating NFT collections. The objective is to lower the barrier to entry for artists, fostering a more inclusive and vibrant ecosystem while maintaining network integrity and preventing spam.

        +

        This RFC proposes changing the current deposit requirements on the Polkadot and Kusama Asset Hub for creating NFT collection, minting an individual NFT, and lowering it's coresponding metadata and attribute deposit. The objective is to lower the barrier to entry for NFT creators, fostering a more inclusive and vibrant ecosystem while maintaining network integrity and preventing spam.

        Motivation

        -

        The current deposit of 10 DOT for collection creation on the Polkadot Asset Hub presents a significant financial barrier for many artists. By lowering the deposit requirements, we aim to encourage more artists to participate in the Polkadot NFT ecosystem, thereby enriching the diversity and vibrancy of the community and its offerings.

        +

        The current deposit of 10 DOT for collection creation (along with 0.01 DOT for item deposit and 0.2 DOT for metadata and attribute deposit) on the Polkadot Asset Hub and 0.1 KSM on Kusama Asset Hub presents a significant financial barrier for many NFT creators. By lowering the deposit requirements, we aim to encourage more NFT creators to participate in the Polkadot NFT ecosystem, thereby enriching the diversity and vibrancy of the community and its offerings.

        The actual implementation of the deposit is an arbitrary number coming from Uniques pallet. It is not a result of any economic analysis. This proposal aims to adjust the deposit from constant to dynamic pricing based on the deposit function with respect to stakeholders.

        Requirements

          @@ -226,8 +243,11 @@

        Previous discussions have been held within the Polkadot Forum community and with artists expressing their concerns about the deposit amounts. Link.

        Explanation

        +

        This RFC proposes a revision of the deposit constants in the nfts pallet on the Polkadot Asset Hub. The new deposit amounts would be determined by a standard deposit formula.

        This RFC suggests modifying deposit constants defined in the nfts pallet on the Polkadot Asset Hub to require a lower deposit. The reduced deposit amount should be determined by the deposit adjusted by the pricing mechanism (arbitrary number/another pricing function).

        -

        Current deposit requirements are as follows:

        +

        Current code structure

        +

        Current deposit requirements are as follows

        +

        Looking at the current code structure the currently implemented we can find that the pricing re-uses the logic of how Uniques are defined:

        #![allow(unused)]
         fn main() {
         parameter_types! {
        @@ -238,9 +258,11 @@
         	pub const NftsAttributeDepositBase: Balance = UniquesAttributeDepositBase::get();
         	pub const NftsDepositPerByte: Balance = UniquesDepositPerByte::get();
         }
        -
        -// 
        -parameter_types! {
        +}
        +

        In the existing setup, the Uniques are defined with specific deposit values for different elements:

        +
        #![allow(unused)]
        +fn main() {
        +parameter_types! {
         	pub const UniquesCollectionDeposit: Balance = UNITS / 10; // 1 / 10 UNIT deposit to create a collection
         	pub const UniquesItemDeposit: Balance = UNITS / 1_000; // 1 / 1000 UNIT deposit to mint an item
         	pub const UniquesMetadataDepositBase: Balance = deposit(1, 129);
        @@ -248,7 +270,38 @@ parameter_types! {
         	pub const UniquesDepositPerByte: Balance = deposit(0, 1);
         }
         }
        -

        The proposed change would modify the deposit constants to require a lower deposit. The reduced deposit amount should be determined by deposit adjusted by an arbitrary number.

        +

        As we can see in the code definition above the current code does not use the deposit funtion when the collection in the following instances: UniquesCollectionDeposit and UniquesItemDeposit.

        +

        Proposed Modification Using the Deposit Function

        +

        This proposed modification adjusts the deposits to use the deposit function instead of using an arbitrary number.

        +
        #![allow(unused)]
        +fn main() {
        +parameter_types! {
        +	pub const NftsCollectionDeposit: Balance = deposit(1, 130);
        +	pub const NftsItemDeposit: Balance = deposit(1, 164);
        +	pub const NftsMetadataDepositBase: Balance = deposit(1, 129);
        +	pub const NftsAttributeDepositBase: Balance = deposit(1, 0);
        +	pub const NftsDepositPerByte: Balance = deposit(0, 1);
        +}
        +}
        +

        Calculations viewed bellow were calculated by using the following repository rfc-pricing. +Polkadot +| Name | Current price implementation | Proposed Modified by using the new deposit function | +|---------------------------|----------------------------------|-------------------------| +| collectionDeposit | 10 DOT | 0.20064 DOT | +| itemDeposit | 0.01 DOT | 0.20081 DOT | +| metadataDepositBase | 0.20129 DOT | 0.20076 DOT | +| attributeDepositBase | 0.2 DOT | 0.2 DOT |

        +

        Similarly the prices for Kusama ecosystem were calculated as: +Kusama: +| Name | Current price implementation | Proposed Price in KSM | +|---------------------------|----------------------------------|---------------------------| +| collectionDeposit | 0.1 KSM | 0.006688 KSM | +| itemDeposit | 0.001 KSM | 0.000167 KSM | +| metadataDepositBase | 0.006709666617 KSM | 0.0006709666617 KSM | +| attributeDepositBase | 0.00666666666 KSM | 0.000666666666 KSM |

        +

        Enhanced Approach to Further Lower Barriers for Entry

        +

        In an effort to further lower barriers to entry and foster greater inclusivity, we propose additional modifications to the pricing structure. These proposed reductions are based on a collaborative and calculated approach, involving the consensus of leading NFT creators within the Polkadot and Kusama Asset Hub communities. The adjustments to deposit amounts are not made arbitrarily. Instead, they are the result of detailed discussions and analyses conducted with prominent NFT creators.

        +

        Proposed Code Adjustments

        #![allow(unused)]
         fn main() {
         parameter_types! {
        @@ -259,74 +312,82 @@ parameter_types! {
         	pub const NftsDepositPerByte: Balance = deposit(0, 1);
         }
         }
        -

        Prices and Proposed Prices on Polkadot Asset Hub: -Scroll right

        -
        | **Name**                  | **Current price implementation** | **Price if DOT = 5$**  | **Price if DOT goes to 50$**  | **Proposed Price in DOT** | **Proposed Price if DOT = 5$**   | **Proposed Price if DOT goes to 50$**|
        -|---------------------------|----------------------------------|------------------------|-------------------------------|---------------------------|----------------------------------|--------------------------------------|
        -| collectionDeposit         | 10 DOT                           | 50 $                   | 500 $                         | 0.20064 DOT                   | ~1 $                            | 10.32$                                   |
        -| itemDeposit               | 0.01 DOT                         | 0.05 $                 | 0.5 $                         | 0.005 DOT                 | 0.025 $                          | 0.251$                                |
        -| metadataDepositBase       | 0.20129 DOT                      | 1.00645 $              | 10.0645 $                     | 0.0020129 DOT             | 0.0100645 $                      | 0.100645$                            |
        -| attributeDepositBase      | 0.2 DOT                          | 1 $                    | 10 $                          | 0.002 DOT                 | 0.01 $                           | 0.1$                                 |
        -
        -

        Prices and Proposed Prices on Kusama Asset Hub: -Scroll right

        -
        | **Name**                  | **Current price implementation** | **Price if KSM = 23$** | **Price if KSM goes to 500$** | **Proposed Price in KSM** | **Proposed Price if KSM = 23$**  | **Proposed Price if KSM goes to 500$** |
        -|---------------------------|----------------------------------|------------------------|-------------------------------|---------------------------|----------------------------------|----------------------------------------|
        -| collectionDeposit         | 0.1 KSM                          | 2.3 $                  | 50 $                          | 0.006688 KSM                  | 0.154 $                           | 3.34 $                                    |
        -| itemDeposit               | 0.001 KSM                        | 0.023 $                | 0.5 $                         | 0.000167 KSM                | 0.00385 $                         | 0.0835 $                                 |
        -| metadataDepositBase       | 0.006709666617 KSM               | 0.15432183319 $        | 3.3548333085 $                | 0.0006709666617 KSM       | 0.015432183319 $                 | 0.33548333085 $                        |
        -| attributeDepositBase      | 0.00666666666 KSM                | 0.15333333318 $        | 3.333333333 $                 | 0.000666666666 KSM        | 0.015333333318 $                 | 0.3333333333 $                         |
        -
        -
        -
        -

        Note: This is only a proposal for change and can be modified upon additional conversation.

        -
        +

        Prices and Proposed Prices on Polkadot Asset Hub:

        +

        Polkadot +| Name | Current price implementation | Proposed Prices | +|---------------------------|----------------------------------|---------------------| +| collectionDeposit | 10 DOT | 0.20064 DOT | +| itemDeposit | 0.01 DOT | 0.005 DOT | +| metadataDepositBase | 0.20129 DOT | 0.002 DOT | +| attributeDepositBase | 0.2 DOT | 0.002 DOT |

        +

        Kusama +| Name | Current price implementation | Proposed Price in KSM | +|---------------------------|----------------------------------|---------------------------| +| collectionDeposit | 0.1 KSM | 0.006688 KSM | +| itemDeposit | 0.001 KSM | 0.000167 KSM | +| metadataDepositBase | 0.006709666617 KSM | 0.0006709666617 KSM | +| attributeDepositBase | 0.00666666666 KSM | 0.000666666666 KSM |

        +

        Discussion of Other Proposals

        +

        Several innovative proposals have been considered to enhance the network's adaptability and manage deposit requirements more effectively:

        +

        Enhanced Weak Governance Origin Model

        +

        The concept of a weak governance origin, controlled by a consortium like the System Collective, has been proposed. This model would allow for dynamic adjustments of NFT deposit requirements in response to market conditions, adhering to storage deposit norms.

        +

        Enhancements and Concerns:

        +
          +
        • Responsiveness: To address concerns about delayed responses, the model could incorporate automated triggers based on predefined market indicators, ensuring timely adjustments.
        • +
        • Stability vs. Flexibility: Balancing stability with the need for flexibility is challenging. To mitigate the issue of frequent changes in DOT-based deposits, a mechanism for gradual and predictable adjustments could be introduced.
        • +
        • Scalability: The model's scalability is a concern, given the numerous deposits across the system. A more centralized approach to deposit management might be needed to avoid constant, decentralized adjustments.
        • +
        +

        Function-Based Pricing Model

        +

        Another proposal is to use a mathematical function to regulate deposit prices, initially allowing low prices to encourage participation, followed by a gradual increase to prevent network bloat.

        +

        Refinements:

        +
          +
        • Choice of Function: A logarithmic or sigmoid function is favored over an exponential one, as these functions increase prices at a rate that encourages participation while preventing prohibitive costs.
        • +
        • Adjustment of Constants: To finely tune the pricing rise, one of the function's constants could correlate with the total number of NFTs on AssetHub. This would align the deposit requirements with the actual usage and growth of the network.
        • +
        +

        Linking Deposit to USD(x) Value

        +

        This approach suggests pegging the deposit value to a stable currency like the USD, introducing predictability and stability for network users.

        +

        Considerations and Challenges:

        +
          +
        • Market Dynamics: One perspective is that fluctuations in native currency value naturally balance user participation and pricing, deterring network spam while encouraging higher-value collections. Conversely, there's an argument for allowing broader participation if the DOT/KSM value increases.
        • +
        • Complexity and Risks: Implementing a USD-based pricing system could add complexity and potential risks. The implementation needs to be carefully designed to avoid unintended consequences, such as excessive reliance on external financial systems or currencies.
        • +
        +

        Each of these proposals offers unique advantages and challenges. The optimal approach may involve a combination of these ideas, carefully adjusted to address the specific needs and dynamics of the Polkadot and Kusama networks.

        Drawbacks

        Modifying deposit requirements necessitates a balanced assessment of the potential drawbacks. Highlighted below are cogent points extracted from the discourse on the Polkadot Forum conversation, which provide critical perspectives on the implications of such changes:

        -
        -

        But NFT deposits were chosen somewhat arbitrarily at genesis and it’s a good exercise to re-evaluate them and adapt if they are causing pain and if lowering them has little or no negative side effect (or if the trade-off is worth it). --> joepetrowski

        -
        -
        -

        Underestimates mean that state grows faster, although not unbounded - effectively an economic subsidy on activity. Overestimates mean that the state grows slower - effectively an economic depressant on activity. --> rphmeier

        -
        -
        -

        Technical: We want to prevent state bloat, therefore using state should have a cost associated with it. --> joepetrowski

        -
        +

        The discourse around modifying deposit requirements includes various perspectives:

        +

        Adjusting NFT deposit requirements on Polkadot and Kusama Asset Hubs involves key challenges:

        +
          +
        1. +

          State Growth and Technical Concerns: Lowering deposit requirements can lead to increased blockchain state size, potentially causing state bloat. This growth needs to be managed to prevent strain on the network's resources and maintain operational efficiency.

          +
        2. +
        3. +

          Network Security and Market Response: Reduced deposits might increase transaction volume, potentially bloating the state, thereby impacting network security. Additionally, adapting to the cryptocurrency market's volatility is crucial. The mechanism for setting deposit amounts must be responsive yet stable, avoiding undue complexity for users.

          +
        4. +
        5. +

          Economic Impact on Previous Stakeholders: The change could have varied economic effects on previous (before the change) creators, platform operators, and investors. Balancing these interests is essential to ensure the adjustment benefits the ecosystem without negatively impacting its value dynamics. However in the particular case of Polkadot and Kusama Asset Hub this does not pose a concern since there are very few collections currently and thus previous stakeholders wouldn't be much affected. As of date 9th January 2024 there are 42 collections on Polkadot Asset Hub and 191 on Kusama Asset Hub with a relatively low volume.

          +
        6. +

        Testing, Security, and Privacy

        -

        The change is backwards compatible. The prevention of "spam" could be prevented by OpenGov proposal to forceDestoy list of collections that are not suitable.

        +

        Security concerns

        +

        The prevention of "spam" could be prevented by OpenGov proposal to forceDestoy list of collections that are not suitable.

        Performance, Ergonomics, and Compatibility

        Performance

        -

        This change is not expected to have a significant impact on the overall performance of the Polkadot Asset Hub. However, monitoring the network closely, especially in the initial stages after implementation, is crucial to identify and mitigate any potential issues.

        -

        Additionally, a supplementary proposal aims to augment the network's adaptability:

        -
        -

        Just from a technical perspective; I think the best we can do is to use a weak governance origin that is controlled by some consortium (ie. System Collective). -This origin could then update the NFT deposits any time the market conditions warrant it - obviously while honoring the storage deposit requirements. -To implement this, we need RFC#12 and the Parameters pallet from @xlc. --> OliverTY

        -
        -

        This dynamic governance approach would facilitate a responsive and agile economic model for deposit management, ensuring that the network remains accessible and robust in the face of market volatility.

        +

        The primary performance consideration stems from the potential for state bloat due to increased activity from lower deposit requirements. It's vital to monitor and manage this to avoid any negative impact on the chain's performance. Strategies for mitigating state bloat, including efficient data management and periodic reviews of storage requirements, will be essential.

        Ergonomics

        -

        The proposed change aims to enhance the user experience for artists, making Polkadot more accessible and user-friendly.

        +

        The proposed change aims to enhance the user experience for artists, traders and utilizers of Kusama and Polkadot asset hub. Making Polkadot and Kusama more accessible and user-friendly.

        Compatibility

        The change does not impact compatibility as redeposit function is already implemented.

        Unresolved Questions

        -
          -
        • -
        +

        There remain unresolved questions regarding the implementation of a function-based pricing model for deposits and the feasibility of linking deposits to a USD(x) value. These aspects require further exploration and discussion to ascertain their viability and potential impact on the ecosystem.

        -
          -
        • -
        -

        If accepted, this RFC could pave the way for further discussions and proposals aimed at enhancing the inclusivity and accessibility of the Polkadot ecosystem. Future work could also explore having a weak governance origin for deposits as proposed by Oliver.

        +

        We recommend initially lowering the deposit to the suggested levels. Subsequently, based on the outcomes and feedback, we can continue discussions on more complex models such as function-based pricing or currency-linked deposits.

        +

        If accepted, this RFC could pave the way for further discussions and proposals aimed at enhancing the inclusivity and accessibility of the Polkadot ecosystem.