Functions
Functions in Scilla are abstracted a level away from Transitions and Procedures. Functions are available to be used by libraries and used in a forall statement as the function to be executed. Functions can also be used as helper methods in Transitions and Procedures.
Let's examine how a function is written and how it's returned.
The below function takes a singular argument of an Optional Uint128, the function has to return the same type, so in the case of no match (None), we will return Uint128 representation of zero, in the case where we have Some, we'll return the Uint128 representation of that value.
let get_val_from_maybe_uint128 = (* Name of the function *) fun (some_val: Option Uint128) => (* Argument, in this case an unwrapped Option *) match some_val with (* Scilla expression begins here *) | Some val => val (* Unwraps value and returns *) | None => uint128_zero (* In the case of no match, return uint128 0, function return Some uint128 *) end
In our implementation, we can call on this function to unwrap any Option Uint128 without verbose Some/None pattern matching.
let uint128_zero = Uint128 0let user_map : Map ByStr20 Uint128 = Emp ByStr20 Uint128
(* Map of ByStr20 Uint128 maps a user to a token *)procedure ExampleFunctionCall() (* get a Some/None Uint128 value*) maybe_user_uint128_value <- user_map[recipient];
(* return Uint128 If None return 0 *) user_balance = get_val_from_maybe_uint128 maybe_user_uint128_value; user_balance_is_zero = builtin eq user_balance uint128_zero
(* act *) match user_balance_is_zero with | True => (* user either has 0 balance OR wasn't present in the Map *) | False => endend
#
Common functions examples#
blk_leqblk_leq is a library function that takes two blocks. It defines two boolean variables bc1
and bc2
.
If the first block is less than the second variable bc1
is set to true.
If the first block is equal to the second variable bc2
is set to true.
The ORB
builtin from the Bools.Util performs a logical OR operator, returning true if either bc1
or bc2
are true.
let blk_leq = fun (blk1 : BNum) => fun (blk2 : BNum) => let bc1 = builtin blt blk1 blk2 in let bc2 = builtin eq blk1 blk2 in orb bc1 bc2
transition Implementation(query_block: BNum, current_block: BNum) less_or_equal_to_query = blk_leq query_block current_block;end
#
muldivGiven the amount of tokens a user has, the total of the pool, and the amount of rewards - returns users percentage of rewards compared to the rest of the pool.
(* Compute "(x * y) / z" with protection against integer overflows *)let muldiv : Uint128 -> Uint128 -> Uint128 -> Uint128 = fun (x : Uint128) => fun (y : Uint128) => fun (z : Uint128) => let x256 = uint128_to_uint256 x in let y256 = uint128_to_uint256 y in let z256 = uint128_to_uint256 z in let x_mul_y256 = builtin mul x256 y256 in let res256 = builtin div x_mul_y256 z256 in let ores128 = builtin to_uint128 res256 in match ores128 with | None => (* this must never happen, hence we throw an integer overflow exception *) let max_uint128 = Uint128 340282366920938463463374607431768211455 in let fourtytwo128 = Uint128 42 in builtin mul max_uint128 fourtytwo128 | Some res128 => res128 end
#
uint128_to_uint256let uint128_to_uint256 : Uint128 -> Uint256 = fun (x : Uint128) => let ox256 = builtin to_uint256 x in match ox256 with | None => (* this never happens, hence we throw a division by zero exception just in case *) let zero = Uint256 0 in builtin div zero zero | Some x256 => x256 end
#
uint128_differencelet uint128_difference = fun (old: Uint128) => fun (new: Uint128) => let a = builtin lt old new in match a with | True => builtin sub new old | False => builtin sub old new end
#
eqByStr20Takes two addresses and returns a Bool
from builtin eq
if the addresses are equal.
let eqByStr20 = fun(bs1: ByStr20) => fun(bs2: ByStr20) => builtin eq bs1 bs2
#
build_pairTakes two arguments and constructs a Pair object from them.
let build_pair = fun (input_to_address : ByStr20) => fun (input_token_uri : String) => Pair {ByStr20 String} input_to_address input_token_uri
#
(Generics) get_option_valueAllows for any generic optional type to be unwrapped using tfun 'A
where 'A
is some type.
let get_option_value = tfun 'A => fun (default: 'A) => fun (opt_val: Option 'A) => match opt_val with | Some v => v | None => default end