5

I'm looking at ink! contracts and chain extensions. Two questions that came up that I did not find an answer by browsing the docs. Both questions are related to the design of integrating ink! with parachain runtimes.

  1. Why are chain extensions explicitly defined vs. giving ink! by default read access to all pallets' storage items and dispatchable functions? It seems quite the overhead to maintain both chain extensions and the pallets themselves. Both, storage and dispatchable functions are publicly accessible anyway so I was surprised, ink! needs to have explicitly stated chain extensions. What was the reason for this design decision?

  2. Why do chain extensions use function ids? In construct_runtime pallets already get an id, plus the pallets' storage items and dispatchable functions have explicit names. Using function ids in the chain extensions, I see two down sides: (1) ink! contract developers need to look up a potentially very long list of chain extension function ids that makes it error-prone during development and review as one might easily confuse function 1101 and 1011 that might have different functionality. (2) For runtime engineers, there seems to be an extra burden to ensure that chain extension function ids are maintained in parallel to the rest of the runtime code. What was the reason for this design decision?

2 Answers 2

3

Why are chain extensions explicitly defined vs. giving ink! by default read access to all pallets' storage items and dispatchable functions?

Contracts do have access to dispatchables. The docs there also explain why we still need chain extensions: Dispatchables can't read data. They are setters. Allowing contracts to read arbitrary runtime storage is not viable because that would effectively prevent any storage migrations since contracts will then depend on storage layout. A solution for reading data that does not require a chain extension will be implemented soon and is called view functions. With both of those things chain extensions might not be required anymore for the vast majority of use cases.

Why do chain extensions use function ids? In construct_runtime pallets already get an id, plus the pallets' storage items and dispatchable functions have explicit names.

This assumes that a chain extension is always just a strict wrapper around pallet dispatchables. That might be true for many and those should be replaced by call_runtime (as explained above). For the rest there might not be such a strict correlation and hence individual identifiers are needed.

1
4

I.
(chain extension = CE)

Yes maintaining CE is an overhead. Especially that most of CE will be a 1o1 wrapper around dispatchable and query functions of a given pallet.

But smart-contracts are not meant to be updated. There is upgrade-able contracts but this targets specific use cases (bigger dApps managed by a DAO). But token standards for example will not be upgreadable (and some of them can use CE like an PSP22 pallet-assets for ex). So implementing contracts to pallet connection at CE level ensure backward compatibility. Chain extension is a stable API
A real world example: assets-pallet is evolving, it's API is not stable. If a smart-contracts call destroy_asset() to pallet-assets but the pallet API is updated, contracts become unusable. But updating inside the CE will ensure it will not break the contract as an runtime upgrade will fix the body of the CE function.

Also CE can abstract logic to ease the use in a smart-contract (in the case of an XCM CE) and also delegates some computation to runtime (in order to lower the size of the contract) like crypto singature verification.

EDIT (forgot to mention): a runtime call to any dispatchable is already availbale in ink! call_runtime and being stabilized.

II.
for runtime devs: functions ids are not meant to be updated (or all contracts using it will be unusable). There is a registry for chain-extension that can be used by several runtime. But id for the CE are not in collision with construct_runtime see here

for smart-contracts devs: these ids can be abstracted like here and used like here. The usage in ink! is being updated to make this kind of implementation easier. I don't think this is error prone for developers because a call to a non existing CE (an id that does't match) will throw DecodingFailed error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.