Patract Hub’s treasury proposal for Ask! v0.2 (ink! in AS)

3yrs ago
0 Comments

img
Patract Hub had finished the development for Ask! v0.1 (funded by Treasury #66) and written a report #494. Ask!'s goal is to provide a set of contract framework and compilation tools using AssemblyScript (aka AS) as the programming language. Contracts written through Ask! can run in the FRAME Contracts Pallet, and eventually can call each other with contracts written by ink!.

v0.2 main functions

This proposal will add the following new features on the basis of v0.1.

1. Add spread and packed data storage methods

In the v0.1, we have implemented the basic data types i8/u8, i16/u16, i32/u32, i64/u64, string, The save and load function of bool, in the v0.2, we will support the save and load of map, array, object and other composite data types. In order to provide flexibility in data storage, but also for storage efficiency on certain scenarios, we will provide two storage methods: spread and packed.

  • @storage is specified as a persistent storage class, and it is stored in the way of spread by default, that is: the preprocessor will generate a key for each member in the storage class, and then use the hash of this key as the index , save the value of the member variable to the chain, and the saved data value is the original value of the member variable, without compression and other operations;
  • The packed method is used to store a member (especially compound members, such as object, map, array) in a packed manner. If a member is designated as a packed member, its sub-members will not continue to expand, but to save and load as a whole. And it will be compressed when saving, and decompressed when loading. The members stored in packed method need to be explicitly specified by the developer using the @packed annotation.

For the part of the composite type, the types commonly used in std are basically implemented in ink!. As far as Ask! is concerned, this version provides a **complete infrastructure for composite types **, and implements the most commonly used composite types. Therefore, like ink!, the corresponding realization of multiple composite types needs to be gradually supplemented in future versions.

2. Add new annotations and extend the supported annotation functions

The basic functions of the four annotations @contract, @storage, @constructor, and @message have been implemented in the v0.1. In this proposal, their functions will be improved and @event annotations will be introduced to support event functions.

  • Introduce @ignore and @packed for @storage class.
    • The @ignore annotation is used to indicate that a particular member variable does not need to be persistently stored. It only saves the set value during one call, and after the call is completed, it is destroyed from memory.
    • The @packed annotation is used to indicate that a member variable is stored in a packed and compressed manner.
  • Introduce parameters payable, mutates, selector for @message annotation.
    • The payable parameter is used to indicate whether the message can accept value. The default value is false.
    • The mutates parameter is used to indicate whether the message changes the value of the stored data. The default value is true.
    • The selector parameter is to specify the selector of the message, that is, if the name of the message is changed, its selector will also use the specified value.
  • Added @event and @topic annotations to support event functions.
    • @event acts on the class, and the preprocessor will generate the emit logic code for this class.
    • @topic acts on the member variables of the event class. The marked member variables will be written into the topic field.

3. Add contract inheritance function

This function is mainly for the preprocessor to process the inheritance relationship between two classes annotated with @contract. AS language itself supports class inheritance, so the main job of the preprocessor is to process @message, @constructor , @storage , these three annotations related to the contract function. Due to class inheritance, the message and constructor methods will be overridden. At this time, the preprocessor determines the call of the call entry function based on the actual contract writing assign logic, and generate the content of the corresponding field in metadata.json.

The function will follow the following principles:

  • The @constructor method is mainly based on subclasses. If it is not provided in the subclass, it is ignored. Because the parent class cannot know the member variables in the subclass, it cannot initialize the contract completely.
  • The @message method uses the union of all messages in the parent class and the subclass. If an override occurs, the message in the subclass is the main one.
  • @storage is not encapsulated, the inheritance relationship is determined by the developer.

ink! currently does not have the ability to inherit/reuse contracts, so Ask! has no reference samples, see issue: [https://github.com/paritytech/ink/issues/625](https://github.com /paritytech/ink/issues/625). In this version, Ask! will implement the corresponding grammatical features of AssemblyScript to simulate the effect of contract inheritance in Solidity.

Because there is no reference sample in this part, the time-consuming implementation may be biased, the completeness of the implementation cannot be clearly guaranteed, and there may be some edge problems that cannot be handled. In short, this part will be designed with reference to the implementation of Solidity. If this part can be implemented successfully, the Ask! contract has features that the ink! contract does not have, and this feature is of great significance to the prosperity of the contract ecosystem .

4. Add the function of cross-contract call by specifying @dynamic class

In the v0.1 version, we have supported the function of using Abi.ts for cross-contract calls, that is, using the following methods:

  let data = Abi.encode("addFunc", [new UInt32(1), new UInt32(2)]);
  let val = this.another.call(data);

However, this method is not conducive to code reuse and maintenance, so the @dynamic annotation is introduced to indicate that a class can be called across contracts.

The @dynamic function is the cornerstone of the definition of contract standards, and is an indispensable function in the contract. Based on this function, the interface can be designed for the contract and the agreement can be made similar to ERC20.

@dynamic acts on the class, the class marked as dynamic, the preprocessor will generate remote call logic for each of its methods, developers do not need to write implementation logic for the methods of the dynamic class. The use of dynamic will be as follows The code shows:

// define a class as dynamic
@dynamic
class IERC20 {
    transfer(from: AccountId, to: AccountId, value: u128): void {}
}

// use dynamic class.
let ksm = new IERC20(new AccountId('0x12345678...'));
ksm.transfer(msg.sender, this.address, msg.value);

Here we don't use the interface keyword, because the interface in AS cannot be a new instance, and the syntax cannot support such an operation.

The definition of @dynamic is similar to the function of interface in Solidity. ink! tries to use #[ink::trait_definition] to implement this. The current design of this part is very imperfect, and a new design has been proposed recently. For details, please refer to the issue: [https://github.com/paritytech/ink/issues/631](https://github.com/ paritytech/ink/issues/631). On the other hand, we believe that the current implementation of ink! contains many problems, see issue:[https://github.com/paritytech/ink/issues/683](https://github.com/paritytech/ink/ issues/683).

Through the above discussion, it can be seen that this feature needs to be carefully designed and there are also various problems in the current ink! design. Therefore, this function may encounter unexpected problems in practice, so this part may also exceed the expected time in practice. Due to language features, we expect that the implementation of this part should be easier than the implementation of ink!.

On the other hand, we hope that the contracts written by Ask! and ink! can call each other. Therefore, in this version we will use this function to design simple cases, for example, manually write the corresponding @dynamic annotated class for the content of the ink! contract, and test the mutual call. But if the ink! contract needs to be more smoothly combined with the Ask! contract, for example, to provide the function of parsing ink!’s metadata to automatically generate the corresponding @dynamic modified class, you need to pay a lot of extra work to design according tools. For example, combine this function with ask-cli. These extra workloads are not included in the implementation of this version and will be arranged in subsequent versions.

Expanded issues in v0.1

In v0.1, we discussed with Parity team about the type generation part in the contract metadata. The type information of metadata is very useful for third-party applications. Currently, the scale-info library is used in ink! as a library for generating contract type information. This library comes from:

@Robin from the parity team informed that the current scale-info is not mature enough to cover many possible situations, so it cannot be used in the Runtime of Substrate to help the Runtime generate type information in the Runtime (so the polkadot.js api needs developer to provide Extending types). And scale-info is more closely bound to the rust syntax, and in many cases it cannot be applied to the type of AS.

Therefore, for the type information part of the contract metadata, we plan to redesign a tool library for AS types and similar in function to scale-info. Since this library is for AS, its corresponding third-party parsing part also needs to be implemented. Therefore, corresponding to this library, we need to add corresponding implementations in the SDKs of different languages:

Except for polkadot.js, the SDKs of other languages ​​are controlled by Patract, so theoretically, we can finally achieve the type information analysis corresponding to Ask!.

However, the workload of implementing this library and the SDK of the corresponding language is huge and cumbersome. On the other hand, the export of type information does not affect the execution of the contract itself.

At the same time, scale-info itself is not mature. ** Therefore, this part will not be planned to be implemented in this version (v0.2), but is planned to be in a later version. **

Detailed timeline of v0.2 (10 weeks)

  • Week 1~3 (3 developers):

    1. Design spread and packed storage solutions.
    2. Implement map, array and object support spread and packed layout storage methods.
    3. Implement the compression and decompression logic in packed mode.
  • Week 4~5 (3 developers):

    1. Implement the @event annotation, including the @event sub-annotation @topic. Implement the event function in the contract.
    2. Add sub-notes of @storage annotation.
    • @ignore: Ignored data members, marked data members will not be persisted.
    • @packed: Persistence in packed mode for array&map and other types. By default, persistence in spread mode is performed.
    1. Add sub-annotation of @message annotation:Supports annotations like @message(payable, mutates = false, selector='0x2345678').
    • payable: Indicates that the message accepts the transfer value, the default is not to accept.
    • mutates: Indicates whether the message changes the state variable. The default value is true.
    • selector: Specify the selector of the message, no matter what the name of the message is, the specified selector is used.
  • Week 6~7 (3 developers): Implement @dynamic annotation function.

    1. Define the code generation logic of the dynamic annotation.
    2. Generate parameter analysis of dynamic class method, function body implementation and return value processing logic.
  • Week 8~10 (3 developers): Implement contract inheritance function.

    1. Implement a single contract entry, hide the parent class as the contract entry.
    2. Get the union of all messages on the inheritance link, and generate the call method and metadata.json information.
    3. Get the @constructor method information on the inheritance link and hide the constructor methods in all parent classes.
    4. Generate a compilable contract expansion file and compile it into the correct wasm bytecode.

Cost of v0.2 (30 developers * weeks)

  • Operating activities: $6000 ( Rent and Devices: $200 per developer * week )
  • Employee payments: $87000 ($2900 per developer * week)
  • Total Cost: $93000 and monthly average: $211 / KSM
  • Treasury Proposal: 440 KSM

Verification of v0.2: GitHub source code & sample contracts

The sample contracts will contain the following:

  1. Realize the full functions of ERC20 and ERC721 contracts.
  2. Through inheritance, reuse contracts that have been written and verified.
  3. Use dynamic methods for cross-contract calls.
  4. Design a simple case to show how the Ask! and ink! contracts call each other.
Up
Comments
No comments here