Smart contract annotations
Smart contract functions are annotated depending on the activity they perform. These annotations are checked at compile time.
A function definition or prototype can only be annotated once. Attempting to use more than annotation in a function will raise a compile-time error.
@init
The @init
function defines a contract constructor that sets the state of the contract prior to any operations performed on it. It is called once and once only on contract initialisation/deployment. The name of the @init
function can be anything at all.
For example, the following function initialises a contract by creating a State
type to represent the owner's account which then receives an initial supply of FET tokens.
@init
function initialise(owner: Address)
var INITIAL_SUPPLY = 100000000000u64;
var account = State<UInt64>("owner");
account.set(INITIAL_SUPPLY);
endfunction
function main()
var owner = Address("2ifr5dSFRAnXexBMC3HYEVp3JHSuz7KBPXWDRBV4xdFrqGy6R9");
initialise(owner);
endfunction
Only one @init
function per contract is allowed; attempting to define more than one will raise a compile-time error. It must take no arguments or only an Address
, and its return type must be either void
or Int64
.
Remember
We use main()
in the examples to allow for testing smart contract code outside of a ledger environment.
@action
The @action
annotation signifies a function which performs a transaction.
A smart contract must have one or more functions annotated with @action
. In order for a function to be callable from other smart contracts, it must be annotated with @action
, otherwise it will be effectively considered private.
You cannot run an etch
smart contract on the Python Ledger API without an @action
function and it is these functions that trigger the charging rules for data persistence fees.
An @action
return type must be either void
or Int64
.
The following function performs a transaction between two parties. In the worst case, this function needs two shards for data storage.
@action
function transfer(from: Address, to: Address, amount: UInt64)
var from_balance = State<UInt64>(from);
from_balance.set(1000u64);
var to_balance = State<UInt64>(to);
to_balance.set(0u64);
// check if all the conditions are valid
if (from_balance.get() <= amount)
panic("Argh!");
endif
from_balance.set(from_balance.get() - amount);
to_balance.set(to_balance.get() + amount);
endfunction
function main()
var owner = Address("2ifr5dSFRAnXexBMC3HYEVp3JHSuz7KBPXWDRBV4xdFrqGy6R9");
var user = Address("2ifr5dSFRAnXexBMC3HYEVp3JHSuz7KBPXWDRBV4xdFrqGy6R9");
transfer(owner, user, 100u64);
endfunction
@query
Query functions are read-only functions that allow you to view data residing on the ledger. Their return type can not be void
.
The following function queries the balance of an Address
.
@query
function balance(address : Address) : UInt64
var account = State<UInt64>(address);
account.set(100u64);
return account.get();
endfunction
function main()
var owner = Address("2ifr5dSFRAnXexBMC3HYEVp3JHSuz7KBPXWDRBV4xdFrqGy6R9");
var owner_balance = balance(owner);
printLn(owner_balance);
endfunction