Contract Decorators
Class Decorator#
@contract#
Usage#
@contract is a class decorator. The decorated class will automatically become an instance of the smart contract. Its sub-fields support @constructor and @message decorator decoration.
@contract decorator implements IContract interface. IContract interface fulfills ABI interfaces defined in
pallet-contract. ask! will generate methods entry points of related ABI interfaces: deploy(): i32 call(): i32 forpallet-contract. Therefore, only@contractclass can be define per one contract entry file.
contructormethod in@contractcan have no parameters since every contract method call requires instantiation throughconstrutor
@contractclass supports inheritence
Example#
@contractexport class ERC20 { @state balances: SpreadStorableMap<AccountId, UInt128> = new SpreadStorableMap<AccountId, UInt128>(); @state allowances: SpreadStorableMap<AccountId, SpreadStorableMap<AccountId, UInt128>> = new SpreadStorableMap<AccountId, SpreadStorableMap<AccountId, UInt128>>();
@state totalSupply: u128 = u128.Zero; @state name_: string = ""; @state symbol_: string = "" @state decimal_: u8 = 0;
constructor() { }}You can inherit it in another class
@contract@doc({"desc": "MyToken conract that extended erc20 contract"})class MyToken extends ERC20 {
constructor() { super(); }}@dynamic#
Usage#
The @dynamic decorator is used to decorate the APIs of a contract that already exists on the chain. By declaring the contract interface on the chain in the @dynamic class, ask will automatically generate the corresponding cross-contract call code.
For details, please refer Cross-Contract calling
Property Decorator#
@state#
Usage#
@state decorator is used to mark the specific member variable as state variable while the ones not decorated are class variables. In v0.2, all variables are default as blockchain state variables. Since we moved @storage into @contract class for better inheritence, we now have to sperate blockchain state variables and normal class properties by having @state decorator.
Config#
lazy: boolean. While lazy is true, that means while a state variable gets changed multiple times in a contract call, only the last change will be synced to blockchain. The default value of lazy is true. While lazy is false, then every change made to the state variable will be synced to blockchain.eg.
@state({"lazy": false})
Example#
@state balances: SpreadStorableMap<AccountId, UInt128> = new SpreadStorableMap<AccountId, UInt128>(); @state allowances: SpreadStorableMap<AccountId, SpreadStorableMap<AccountId, UInt128>> = new SpreadStorableMap<AccountId, SpreadStorableMap<AccountId, UInt128>>();
@state totalSupply: u128 = u128.Zero; @state name_: string = ""; @state symbol_: string = "" @state decimal_: u8 = 0; @state({"lazy": false}) is_paused: boolean = false;Method Decorator#
@constructor#
This decorator is used to decorate public methods underneath @contract class as the constructor API to instantiate contract
Usage#
- least one
@constructormethod must be defined per@contractclass - multiple
@contructormethods per@contractclass
Parameter <*scale-codec>#
@contructor method takes any number of parameters as long as the parameter implement SCALE codec.
Return <void>#
@contructor method doesn't support return value that means void as the return type.
Config seletor#
selector: string. Use specific selector instead of default selector generated by blake2b.eg.
@constructor({ "selector": "0xAABBccdd" })
Example#
@constructor default(initFlag: bool): void { this.stored.flag = initFlag; }@message#
This decorator is used to decorate public methods underneath @contract class
Usage#
@message method can only be declared under @contractclass
Parameter *<scale-codec>#
- This decorator can only be used with public methods in
@contractclass not including static methods.
Return <scale-codec>#
- Return: The
@messagemethod must have return value and the return type must implement SCALE codec.
Config seletor, mutate, payable#
selector: string. Use specific selector instead of default selector generated by blake2b. eg.@message({"selector": "0xCAFEBABE" })payable: boolean, means this message can accept msg.value. eg.@message({"selector": false})mutates: boolean, eg.`means if this message can modify states of this contract. eg.@message({"mutate": false})`@messagemethod hasmsgvariable to read contract state. eg.msg.senderto get the sender of contract call
Example#
@message transfer(recipient: AccountId, amount: u128): bool { let from = msg.sender; this._transfer(from, recipient, amount); return true; }