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@contract
class can be define per one contract entry file.
contructor
method in@contract
can have no parameters since every contract method call requires instantiation throughconstrutor
@contract
class 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#
UsageThe @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.
#
Configlazy
: 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#
@constructorThis decorator is used to decorate public methods underneath @contract
class as the constructor API to instantiate contract
#
Usage- least one
@constructor
method must be defined per@contract
class - multiple
@contructor
methods per@contract
class
<*scale-codec>
#
Parameter @contructor
method takes any number of parameters as long as the parameter implement SCALE codec.
<void>
#
Return @contructor
method doesn't support return value that means void
as the return type.
seletor
#
Config 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; }
#
@messageThis decorator is used to decorate public methods underneath @contract
class
#
Usage@message
method can only be declared under @contract
class
*<scale-codec>
#
Parameter - This decorator can only be used with public methods in
@contract
class not including static methods.
<scale-codec>
#
Return - Return: The
@message
method must have return value and the return type must implement SCALE codec.
seletor
, mutate
, payable
#
Config 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})`@message
method hasmsg
variable to read contract state. eg.msg.sender
to 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; }