The Scilla Standard Library

The Scilla standard library contains five libraries: BoolUtils.scilla, IntUtils.scilla, ListUtils.scilla, NatUtils.scilla and PairUtils.scilla. As the names suggests these contracts implement utility operations for the Bool, IntX, List, Nat and Pair types, respectively.

To use functions from the standard library in a contract, the relevant library file must be imported using the import declaration. The following code snippet shows how to import the functions from the ListUtils and IntUtils libraries:

import ListUtils IntUtils

The import declaration must occur immediately before the contract’s own library declaration, e.g.:

import ListUtils IntUtils

library WalletLib
... (* The declarations of the contract's own library values and functions *)

contract Wallet ( ... )
... (* The transitions and procedures of the contract *)

Below, we present the functions defined in each of the library.

BoolUtils

  • andb : Bool -> Bool -> Bool: Computes the logical AND of two Bool values.
  • orb  : Bool -> Bool -> Bool: Computes the logical OR of two Bool values.
  • negb : Bool -> Bool: Computes the logical negation of a Bool value.
  • bool_to_string : Bool -> String: Transforms a Bool value into a String value. True is transformed into "True", and False is transformed into "False".

IntUtils

  • intX_eq : IntX -> IntX -> Bool: Equality operator specialised for each IntX type.
let int_list_eq = @list_eq Int64 in

let one = Int64 1 in
let two = Int64 2 in
let ten = Int64 10 in
let eleven = Int64 11 in

let nil = Nil {Int64} in
let l1 = Cons {Int64} eleven nil in
let l2 = Cons {Int64} ten l1 in
let l3 = Cons {Int64} two l2 in
let l4 = Cons {Int64} one l3 in

let f = int64_eq in
(* See if [2,10,11] = [1,2,10,11] *)
int_list_eq f l3 l4
  • uintX_eq : UintX -> UintX -> Bool: Equality operator specialised for each UintX type.
  • intX_lt : IntX -> IntX -> Bool: Less-than operator specialised for each IntX type.
  • uintX_lt : UintX -> UintX -> Bool: Less-than operator specialised for each UintX type.
  • intX_neq : IntX -> IntX -> Bool: Not-equal operator specialised for each IntX type.
  • uintX_neq : UintX -> UintX -> Bool: Not-equal operator specialised for each UintX type.
  • intX_le : IntX -> IntX -> Bool: Less-than-or-equal operator specialised for each IntX type.
  • uintX_le : UintX -> UintX -> Bool: Less-than-or-equal operator specialised for each UintX type.
  • intX_gt : IntX -> IntX -> Bool: Greater-than operator specialised for each IntX type.
  • uintX_gt : UintX -> UintX -> Bool: Greater-than operator specialised for each UintX type.
  • intX_ge : IntX -> IntX -> Bool: Greater-than-or-equal operator specialised for each IntX type.
  • uintX_ge : UintX -> UintX -> Bool: Greater-than-or-equal operator specialised for each UintX type.

ListUtils

  • list_map : ('A -> 'B) -> List 'A -> : List 'B.

    Apply f : 'A -> 'B to every element of l : List 'A, constructing a list (of type List 'B) of the results.
    (* Library *)
    let f =
      fun (a : Int32) =>
        builtin sha256hash a
    
    (* Contract transition *)
    (* Assume input is the list [ 1 ; 2 ; 3 ] *)
    (* Apply f to all values in input *)
    hash_list_int32 = @list_map Int32 ByStr32;
    hashed_list = hash_list_int32 f input;
    (* hashed_list is now [ sha256hash 1 ; sha256hash 2 ; sha256hash 3 ] *)
    
  • list_filter : ('A -> Bool) -> List 'A -> List 'A.

    Filter out elements on the list based on the predicate f : 'A -> Bool. If an element satisfies f, it will be in the resultant list, otherwise it is removed. The order of the elements is preserved.
    (*Library*)
    let f =
      fun (a : Int32) =>
        let ten = Int32 10 in
        builtin lt a ten
    
    (* Contract transition *)
    (* Assume input is the list [ 1 ; 42 ; 2 ; 11 ; 12 ] *)
    less_ten_int32 = @list_filter Int32;
    less_ten_list = less_ten_int32 f l
    (* less_ten_list is now  [ 1 ; 2 ]*)
    
  • list_head : (List 'A) -> (Option 'A).

    Return the head element of a list l : List 'A as an optional value. If l is not empty with the first element h, the result is Some h. If l is empty, then the result is None.
  • list_tail : (List 'A) -> (Option List 'A).

    Return the tail of a list l : List 'A as an optional value. If l is a non-empty list of the form Cons h t, then the result is Some t. If l is empty, then the result is None.
  • list_foldl_while : ('B -> 'A -> Option 'B) -> 'B -> List 'A -> 'B

    Given a function f : 'B -> 'A -> Option 'B, accumulator z : 'B and list ls : List 'A execute a left fold when our given function returns Some x : Option 'B using f z x : 'B or list is empty but in the case of None : Option 'B terminate early, returning z.
(* assume zero = 0, one = 1, negb is in scope and ls = [10,12,9,7]
 given a max and list with elements a_0, a_1, ..., a_m
 find largest n s.t. sum of i from 0 to (n-1) a_i <= max *)
let prefix_step = fun (len_limit : Pair Uint32 Uint32) => fun (x : Uint32) =>
  match len_limit with
  | Pair len limit => let limit_lt_x = builtin lt limit x in
    let x_leq_limit = negb limit_lt_x in
    match x_leq_limit with
    | True => let len_succ = builtin add len one in let l_sub_x = builtin sub limit x in
      let res = Pair {Uint32 Uint32} len_succ l_sub_x in
      Some {(Pair Uint32 Uint32)} res
    | False => None {(Pair Uint32 Uint32)}
    end
  end in
let fold_while = @list_foldl_while Uint32 (Pair Uint32 Uint32) in
let max = Uint32 31 in
let init = Pair {Uint32 Uint32} zero max in
let prefix_length = fold_while prefix_step init ls in
match prefix_length with
| Pair length _ => length
end
  • list_append : (List 'A -> List 'A ->  List 'A).

    Append the first list to the front of the second list, keeping the order of the elements in both lists. Note that list_append has linear time complexity in the length of the first argument list.
  • list_reverse : (List 'A -> List 'A).

    Return the reverse of the input list. Note that list_reverse has linear time complexity in the length of the argument list.
  • list_flatten : (List List 'A) -> List 'A.

    Construct a list of all the elements in a list of lists. Each element (which has type List 'A) of the input list (which has type List List 'A) are all concatenated together, keeping the order of the input list. Note that list_flatten has linear time complexity in the total number of elements in all of the lists.
  • list_length : List 'A -> Uint32

    Count the number of elements in a list. Note that list_length has linear time complexity in the number of elements in the list.
  • list_eq : ('A -> 'A -> Bool) -> List 'A -> List 'A -> Bool.

    Compare two lists element by element, using a predicate function f : 'A -> 'A -> Bool. If f returns True for every pair of elements, then list_eq returns True. If f returns False for at least one pair of elements, or if the lists have different lengths, then list_eq returns False.
  • list_mem : ('A -> 'A -> Bool) -> 'A -> List 'A -> Bool.

    Checks whether an element a : 'A is an element in the list l : List'A. f : 'A -> 'A -> Bool should be provided for equality comparison.
    (* Library *)
    let f =
      fun (a : Int32) =>
      fun (b : Int32) =>
        builtin eq a b
    
    (* Contract transition *)
    (* Assume input is the list [ 1 ; 2 ; 3 ; 4 ] *)
    keynumber = Int32 5;
    list_mem_int32 = @list_mem Int32;
    check_result = list_mem_int32 f keynumber input;
    (* check_result is now False *)
    
  • list_forall : ('A -> Bool) -> List 'A -> Bool.

    Check whether all elements of list l : List 'A satisfy the predicate f : 'A -> Bool. list_forall returns True if all elements satisfy f, and False if at least one element does not satisfy f.
  • list_exists : ('A -> Bool) -> List 'A -> Bool.

    Check whether at least one element of list l : List 'A satisfies the predicate f : 'A -> Bool. list_exists returns True if at least one element satisfies f, and False if none of the elements satisfy f.
  • list_sort : ('A -> 'A -> Bool) -> List 'A -> List 'A.

    Sort the input list l : List 'A using insertion sort. The comparison function flt : 'A -> 'A -> Bool provided must return True if its first argument is less than its second argument. list_sort has quadratic time complexity.
    let int_sort = @list_sort Uint64 in
    
    let flt =
      fun (a : Uint64) =>
      fun (b : Uint64) =>
        builtin lt a b
    
    let zero = Uint64 0 in
    let one = Uint64 1 in
    let two = Uint64 2 in
    let three = Uint64 3 in
    let four = Uint64 4 in
    
    (* l6 = [ 3 ; 2 ; 1 ; 2 ; 3 ; 4 ; 2 ] *)
    let l6 =
      let nil = Nil {Uint64} in
      let l0 = Cons {Uint64} two nil in
      let l1 = Cons {Uint64} four l0 in
      let l2 = Cons {Uint64} three l1 in
      let l3 = Cons {Uint64} two l2 in
      let l4 = Cons {Uint64} one l3 in
      let l5 = Cons {Uint64} two l4 in
      Cons {Uint64} three l5
    
    (* res1 = [ 1 ; 2 ; 2 ; 2 ; 3 ; 3 ; 4 ] *)
    let res1 = int_sort flt l6
    
  • list_find : ('A -> Bool) -> List 'A -> Option 'A.

    Return the first element in a list l : List 'A satisfying the predicate f : 'A -> Bool. If at least one element in the list satisfies the predicate, and the first one of those elements is x, then the result is Some x. If no element satisfies the predicate, the result is None.
  • list_zip : List 'A -> List 'B -> List (Pair 'A 'B).

    Combine two lists element by element, resulting in a list of pairs. If the lists have different lengths, the trailing elements of the longest list are ignored.
  • list_zip_with : ('A -> 'B -> 'C) -> List 'A -> List 'B -> List 'C ).

    Combine two lists element by element using a combining function f : 'A -> 'B -> 'C. The result of list_zip_with is a list of the results of applying f to the elements of the two lists. If the lists have different lengths, the trailing elements of the longest list are ignored.
  • list_unzip : List (Pair 'A 'B) -> Pair (List 'A) (List 'B).

    Split a list of pairs into a pair of lists consisting of the elements of the pairs of the original list.
  • list_nth : Uint32 -> List 'A -> Option 'A.

    Return the element number n from a list. If the list has at least n elements, and the element number n is x, list_nth returns Some x. If the list has fewer than n elements, list_nth returns None.

NatUtils

  • nat_prev : Nat -> Option Nat: Return the Peano number one less than the current one. If the current number is Zero, the result is None. If the current number is Succ x, then the result is Some x.
  • nat_fold_while : ('T -> Nat -> Option 'T) -> 'T -> Nat -> 'T: Takes arguments f : 'T -> Nat -> Option 'T, z : `T and m : Nat. This is nat_fold with early termination. Continues recursing so long as f returns Some y with new accumulator y. Once f returns None, the recursion terminates.
  • is_some_zero : Nat -> Bool: Zero check for Peano numbers.
  • nat_eq : Nat -> Nat -> Bool: Equality check specialised for the Nat type.
  • nat_to_int : Nat -> Uint32: Convert a Peano number to its equivalent Uint32 integer.
  • uintX_to_nat : UintX -> Nat: Convert a UintX integer to its equivalent Peano number. The integer must be small enough to fit into a Uint32. If it is not, then an overflow error will occur.
  • intX_to_nat : IntX -> Nat: Convert an IntX integer to its equivalent Peano number. The integer must be non-negative, and must be small enough to fit into a Uint32. If it is not, then an underflow or overflow error will occur.

PairUtils

  • fst : Pair 'A 'B -> 'A: Extract the first element of a Pair.
let fst_strings = @fst String String in
let nick_name = "toby" in
let dog = "dog" in
let tobias = Pair {String String} nick_name dog in
fst_strings tobias
  • snd : Pair 'A 'B -> 'B: Extract the second element of a Pair.

Conversions

This library provides conversions b/w Scilla types, particularly between integers and byte strings.

To enable specifying the encoding of integer arguments to these functions, a type is defined for endianness.

type IntegerEncoding =
  | LittleEndian
  | BigEndian

The functions below, along with their primary result, also return next_pos : Uint32 which indicates the position from which any further data extraction from the input ByStr value can proceed. This is useful when deserializing a byte stream. In other words, next_pos indicates where this function stopped reading bytes from the input byte string.

  • substr_safe : ByStr -> Uint32 -> Uint32 -> Option ByStr While Scilla provides a builtin to extract substrings of byte strings (ByStr), it is not exception safe. When provided incorrect arguments, it throws exceptions. This library function is provided as an exception safe function to extract, from a string s : ByStr, a substring starting at position pos : Uint32 and of length len : Uint32. It returns Some ByStr on success and None on failure.
  • extract_uint32 : IntegerEncoding -> ByStr -> Uint32 -> Option (Pair Uint32 Uint32) Extracts a Uint32 value from bs : ByStr, starting at position pos : Uint32. On success, Some extracted_uint32_value next_pos is returned. None otherwise.
  • extract_uint64 : IntegerEncoding -> ByStr -> Uint32 -> Option (Pair Uint64 Uint32) Extracts a Uint64 value from bs : ByStr, starting at position pos : Uint32. On success, Some extracted_uint64_value next_pos is returned. None otherwise.
  • extract_uint128 : IntegerEncoding -> ByStr -> Uint32 -> Option (Pair Uint128 Uint32) Extracts a Uint128 value from bs : ByStr, starting at position pos : Uint32. On success, Some extracted_uint128_value next_pos is returned. None otherwise.
  • extract_uint256 : IntegerEncoding -> ByStr -> Uint32 -> Option (Pair Uint256 Uint32) Extracts a Uint256 value from bs : ByStr, starting at position pos : Uint32. On success, Some extracted_uint256_value next_pos is returned. None otherwise.
  • extract_bystr1 : ByStr -> Uint32 -> Option (Pair ByStr1 Uint32) Extracts a ByStr1 value from bs : ByStr, starting at position pos : Uint32. On success, Some extracted_bystr1_value next_pos is returned. None otherwise.
  • extract_bystr2 : ByStr -> Uint32 -> Option (Pair ByStr2 Uint32) Extracts a ByStr2 value from bs : ByStr, starting at position pos : Uint32. On success, Some extracted_bystr2_value next_pos is returned. None otherwise.
  • extract_bystr20 : ByStr -> Uint32 -> Option (Pair ByStr20 Uint32) Extracts a ByStr2 value from bs : ByStr, starting at position pos : Uint32. On success, Some extracted_bystr20_value next_pos is returned. None otherwise.
  • extract_bystr32 : ByStr -> Uint32 -> Option (Pair ByStr32 Uint32) Extracts a ByStr2 value from bs : ByStr, starting at position pos : Uint32. On success, Some extracted_bystr32_value next_pos is returned. None otherwise.
  • append_uint32 : IntegerEncoding -> ByStr -> Uint32 -> ByStr Serialize a Uint32 value (with the specified encoding) and append it to the provided ByStr and return the result ByStr.
  • append_uint64 : IntegerEncoding -> ByStr -> Uint32 -> ByStr Serialize a Uint64 value (with the specified encoding) and append it to the provided ByStr and return the result ByStr.
  • append_uint128 : IntegerEncoding -> ByStr -> Uint32 -> ByStr Serialize a Uint128 value (with the specified encoding) and append it to the provided ByStr and return the result ByStr.
  • append_uint256 : IntegerEncoding -> ByStr -> Uint32 -> ByStr Serialize a Uint256 value (with the specified encoding) and append it to the provided ByStr and return the result ByStr.

Polynetwork Support Library

This library provides utility functions used in building the Zilliqa Polynetwork bridge. These functions are migrated from Polynetwork’s ethereum support, with the contract itself separately deployed.