Love primitives¶
Prefix & Infix primitives¶
There are two kinds of primitives in the language:
- Prefix primitives are used by putting the primitive before the
arguments:
prim x y z
. - Infix primitves are used by putting the primitive between the
arguments:
x prim y
. Infix primitives are always operators (+
,-
, etc.).
When the type of a primitive is specified, we extend the notation for functions like this:
TYPE_ARG -> TYPE_RESULT
for a primitive with one argumentTYPE_ARG1 -> TYPE_ARG2 -> TYPE_RESULT
for a primitive with two argumentsforall TYPES. ... -> TYPE_RESULT
for a polymorphic primitive
Whereas functions can only take one argument in Liquidity/Michelson (possibly a tuple), primitives can take multiple arguments.
Comparison between values¶
All values are not comparable. Only two values of the following types can be compared with each other:
unit
bool
int
dun
string
bytes
timestamp
keyhash
address
'a * 'b
when'a
and'b
are comparable'a option
,``’a list``,'a set
when'a
is comparable('a, 'b) map
when'a
and'b
are comparable{field1 : 'a; field2 : 'b; ...}
when'a
,'b
, … are comparableA of 'a | B of 'b ...
when'a
,'b
, … are comparable
The following comparison operators are available:
=
: equal<>
: not-equal<
: strictly less<=
: less or equal>
: strictly greater>=
: greater or equal
These operators have type forall 'a. 'a -> 'a -> bool
, hence their type
must be provided with the type application [:TYPE]
Example: =[:bool]
defines the equality on booleans and has type
bool -> bool -> bool
.
The function compare : forall 'a. 'a -> 'a -> int
is a polymorphic function returning an integer, as follows.
compare[:TYPE] x y
* returns 0 if x
and y
are equal
* returns a strictly positive integer if x > y
* returns a strictly negative integer if x < y
Raising exceptions¶
There exist two kind of exceptions in Love: user-defined exceptions
and the Failure
polymorphic exception.
User-defined exceptions are declared in contracts with the keyword
exception
and a list of types. They are raised with they keyworkraise
, and can be catched when encapsulated intry ... with EXCEPTION ->
.raise
is a special primitive that takes an exception in argument and returns a value of typeforall 'a, 'a
.exception MyException of bool val test (p : bool) : int = try ( if p then (raise (MyException true)) [:int] else 0 ) with | MyException b -> -1
failwith : forall 'a. 'a -> (forall 'b. 'b)
: makes the current transaction and all its internal transactions fail. No modification is done to the context. The argument can be any value (often a string and some argument), the system will display it to explain why the transaction failed. The argument and return type must be specified as the function is polymorphic.val%entry default storage d (p : unit) = let unit_value = (failwith [:string] "The transaction failed") [:unit] in ([][:operation], storage)
Operations on tuples¶
Simple projection:
t.n
wheren
is a constant positive-or-nul int: returns then
-th element of the tuplet
. Starts at0
.type storage = int val%entry default storage d (p : int * int) = let new_storage = p.1 in ([][:operation], new_storage)
Tuple projection:
t.(n_1,n_2,...)
wheren_i
is a constant positive-or-nul int for eachi
: returns the tuple with the elements corresponding to(n_1,n_2,...)
type storage = int * int val%entry default storage d (p : int * int * bool) = let new_storage = p.(0,1) in ([][:operation], new_storage)
Tuple update:
t <- (EXP_1,EXP_2,...)
returns the tuple where each elementi
has been replaced byEXP_i
.EXP_i
can either be an expression or_
, which does not change thei
-th element of the tuple.
type storage = int * int * int val%entry default storage d (p : unit) = let new_storage = storage <- (_, storage.1 + 1) in ([][:operation], new_storage)
Operations on numeric values¶
Operations on numeric values are not polymorphic, each operator define a specific numeric operation.
- Additions
+ : int -> int -> int
++ : nat -> nat -> nat
++! : nat -> int -> int
+!+ : int -> nat -> int
+$ : dun -> dun -> dun
+:! : timestamp -> int -> timestamp
+!: : int -> timestamp -> timestamp
+:+ : timestamp -> nat -> timestamp
++: : nat -> timestamp -> timestamp
- Substraction
- : int -> int -> int
-+ : nat -> nat -> int
-+! : nat -> int -> int
-!+ : int -> nat -> int
-$ : dun -> dun -> dun
-: : timestamp -> timestamp -> int
-:! : timestamp -> int -> timestamp
-!: : int -> timestamp -> timestamp
-:+ : timestamp -> nat -> timestamp
-+: : nat -> timestamp -> timestamp
- Multiplication
* : int -> int -> int
*+ : nat -> nat -> nat
*+! : nat -> int -> int
*!+ : int -> nat -> int
*$! : dun -> int -> dun option
*!$ : int -> dun -> dun option
*$+ : dun -> nat -> dun
*+$ : nat -> dun -> dun
- Division (returns
None
when the second argument is zero)/ : int -> int -> (int * int) option
/+ : nat -> nat -> (nat * nat) option
/+! : nat -> int -> (int * int) option
/!+ : int -> nat -> (int * int) option
/$ : dun -> dun -> (int * dun) option
/$! : dun -> int -> (dun * dun) option
/$+ : dun -> nat -> (dun * dun) option
NB: Arithmetic operators syntax follows a certain logic. The first characher represents the operation, followed by symbols representing the argument types.
!
forint
+
fornat
$
fordun
:
fortimestamp
For example, +!:
is the operator adding int
s
to timestamp
s.
- Bitwise operators
land | lor | lxor | lsl | lsr : int -> int -> int
nand | nor | nxor | nlsl | nlsr : nat -> nat -> nat
- Boolean operators (not lazy)
&&
: boolean and||
: boolean or|&
: boolean xornot
: boolean negation
Translators¶
Int.of_nat : nat -> int
Transforms a positive integer to a signed integer.val decr (x : nat) : int = Int.of_nat x - 1
Nat.of_int : int -> nat option
Transforms an integer to a positive integer. If the integer in argument is negative, it returnsNone
.val is_positive (x : int) : bool = match Nat.of_int x with None -> false | Some _ -> true
Address.of_keyhash : keyhash -> address
Transforms a keyhash to an addressval to_address (x : keyhash) : address = Address.of_keyhash x
Keyhash.of_address : address -> keyhash option
Transforms an address to a keyhash. If the address in argument is a contract, it returnsNone
.val is_contract (x : address) : bool = match Keyhash.of_address x with None -> true | Some _ -> false
Operations on lambdas¶
( |> ) : 'a -> ('a -> 'b) -> 'b
Applies a function to its argument.type storage = nat val%entry default storage d (b : unit) = let b = storage |> Bytes.pack [:storage] |> Bytes.unpack<:nat> in match b with None -> ([][:operation], storage) | Some b -> ([][:operation], b)
Operation on lists¶
Lists are immutable data structures containing values (of any type) that can only be accessed in a sequential order. Since they are immutable, all modification primitives return a new list, and the list given in argument is unmodified.
[] : forall 'a. 'a list
The empty list.val int_list : int list = [] [:int] val nat_list : nat list = [] [:nat] val fun_list : (int -> int) list = [] [:int -> int]
List.cons : forall 'a. 'a -> 'a list -> 'a list
Add a new element at the head of the list. The previous list becomes the tail of the new list. It is equivalent toCONS
in Michelson.type storage = int list val%entry default storage d (p : int) = let new_storage = p :: storage in ([][:operation], new_storage)
( :: ) : forall 'a. 'a -> 'a list -> 'a list
Same asList.cons
, but is an infix operator. The type'a
is automatically inferred and is not required.type storage = int list val%entry default storage d (p : int) = let new_storage = List.cons p storage in ([][:operation], new_storage)
( @ ) : forall 'a. 'a list -> 'a list -> 'a list
. Concatenate two lists into a single list.type storage = int list val%entry default storage d (p : int list) = ([][:operation], storage @ [:int] p)
List.rev : forall 'a. 'a list -> 'a list
Returns the list in the reverse order.type storage = int list val%entry default storage d (p : unit) = ([][:operation], List.rev[:int] storage)
List.length : forall 'a. 'a list -> nat
. Returns the length of the list. It is equivalent toSIZE
in Michelson.type storage = int list val%view storage_size storage (p : unit) : nat = List.length[:int] storage
List.iter: forall 'a. ('a -> unit) -> 'a list -> unit
. Iter the function on all the elements of a list. Since no value can be returned, it can only be used for side effects, i.e. to fail the transaction. It is equivalent toITER
in Michelson.exception Fail type storage = int list val%view check_storage storage (p : unit) : unit = List.iter[:int] (fun (elt : int) -> if (elt <[:int] 0) then (raise Fail) [:unit]) storage
List.fold: forall 'elt. forall 'acc. ('elt -> 'acc -> 'acc) -> 'elt list -> 'acc -> 'acc
. Iter on all elements of a list, while modifying an accumulator. It is equivalent toITER
in Michelson.type storage = int list val%view sum_storage storage (p : unit) : int = List.fold [:int] [:int] (fun (stor_elt : int) (acc : int) -> acc + stor_elt) storage 0
List.map: forall 'a. forall 'b. ('a -> 'b) -> 'a list -> 'b list
. Returns a list with the result of applying the function on each element of the list. It is equivalent toMAP
in Michelson.type storage = int list val%entry default storage d (p : int) = let new_storage = List.map[:int][:int] (fun (i : int) -> i + p) storage in ([][:operation], new_storage)
List.map_fold: forall 'a. forall 'acc. forall 'b. ('a * 'acc -> 'b * 'acc) -> 'a list -> 'acc -> 'b list * 'acc
. Returns a list with the result of applying the function on each element of the list, plus an accumulator. It is equivalent toMAP
in Michelson.type storage = int list val%entry default storage d (p : int) = let (new_storage, acc) = List.map_fold[:int] [:int] [:int] (fun (elt : int) (acc : int) -> ( elt + p, elt + acc )) ([1; 2; 3; 4; 5] [:int]) 0 in ([][:operation], new_storage)
The Bytes module¶
Bytes.pack: forall 'a. 'a -> bytes
. Serialize any data to a binary representation in a sequence of bytes. It is equivalent toPACK
in Michelson.type storage = bytes val%entry default storage d (k : address) = let b = Bytes.pack [:address] k in ([][:operation], b)
Bytes.unpack<:TYPE>: bytes -> TYPE option
. Deserialize a sequence of bytes to a value from which it was serialized. The expression should be annotated with the (option) type that it should return. It is equivalent toUNPACK
in Michelson.type storage = address val%entry default storage d (k : bytes) = match Bytes.unpack<:address> k with None -> ([][:operation], storage) | Some a -> ([][:operation], a)
Bytes.length : bytes -> nat
. Returns the size of the sequence of bytes. It is equivalent toSIZE
in Michelson.type storage = nat val%entry default storage d (b : bytes) = ([][:operation], Bytes.length b)
Bytes.concat: bytes list -> bytes
. Append all the sequences of bytes of a list into a single sequence of bytes. It is equivalent toCONCAT
in Michelson.type storage = bytes val%entry default storage d (b : bytes) = ([][:operation], Bytes.concat ([storage; b][:bytes]))
Bytes.slice : nat -> nat -> bytes -> bytes option
. Extract a sequence of bytes within another sequence of bytes.Bytes.slice start len b
extracts the bytes subsequence ofb
starting at indexstart
and of lengthlen
. A return valueNone
means that the position or length was invalid. It is equivalent toSLICE
in Michelson.type frame = {start : nat; size : nat} type storage = bytes val%view get_sub storage (b : frame) : bytes option = Bytes.slice b.start b.size storage
Operation on strings¶
A string is a fixed sequence of characters. They are restricted to the
printable subset of 7-bit ASCII, plus some escaped characters (\n
,
\t
, \b
, \r
, \\
, \"
).
String.length : string -> nat
. Returns the size of the string in characters. It is equivalent toSIZE
in Michelson.type storage = string val%view length storage (p : unit) : nat = String.length storage
String.slice : nat -> nat -> string -> string option
.String.slice start len s
returns a substring of a strings
at the given starting at positionlen
with the specified lengthlen
, orNone
if invalid. It is equivalent toSLICE
in Michelson.type frame = {start : nat; size : nat} type storage = string val%view get_sub storage (b : frame) : string option = String.slice b.start b.size storage
String.concat: string list -> string
. Append all strings of a list into a single string. It is equivalent toCONCAT
in Michelson.type storage = string val%entry default storage d (b : string) = ([][:operation], String.concat ([storage; b][:string]))
^: string -> string -> string
. Infix operator for concatenating two strings.type storage = string val%entry default storage d (k : string) = let new_storage = storage ^ " and then " ^ k in ([][:operation], new_storage)
The Set
module¶
Sets are immutable data structures containing unique values (a comparable type). Since they are immutable, all modification primitives return a new updated set, and the set given in argument is unmodified.
Set.empty: forall 'a. 'a set
. The empty settype storage = int set val%entry default s d (p : unit) = ([][:operation], Set.empty [:int])
Set.cardinal: forall 'a. 'a set -> nat
. The number of elements in a set.type storage = int set val%view storage_size s (p : unit) : nat = Set.cardinal [:int] s
Set.add: forall 'a. 'a -> 'a set -> 'a set
. Add an element to a set, if not present.type storage = int set val%entry add_elt s d (p : int) = ([][:operation], Set.add [:int] p s)
Set.remove: forall 'a. 'a -> 'a set -> 'a set
. Removes an element to a set, if present.type storage = int set val%entry remove_elt s d (p : int) = ([][:operation], Set.remove [:int] p s)
Set.mem: forall 'a. 'a -> 'a set -> bool
. Returnstrue
if the element is in the set,false
otherwise. It is equivalent toMEM
in Michelson.type storage = int set val%view contains storage (p : int) : bool = Set.mem [:int] p storage
Set.iter: forall 'elt. ('elt -> unit) -> 'elt set -> unit
. Apply a function on all elements of the set. Since no value can be returned, it can only be used for side effects, i.e. to fail the transaction. It is equivalent toITER
in Michelson.exception Fail type storage = int set val%view check_storage storage (p : unit) : unit = Set.iter [:int] (fun (elt : int) -> if (elt <[:int] 0) then (raise Fail) [:unit]) storage
Set.fold: forall 'elt. forall 'acc. ('elt -> 'acc -> 'acc) -> 'elt set -> 'acc -> 'acc
. Iter on all elements of a set, while modifying an accumulator.type storage = int set val%view sum_storage storage (p : int) : int = Set.fold[:int][:int] (fun (i : int) (acc : int) -> i + acc) storage 0
Set.map: forall 'a. forall 'b. ('a -> 'b) -> 'a set -> 'b set
. Returns a list with the result of applying the function on each element of the list.type storage = int set val%view incr_storage storage (p : int) : int set = Set.map[:int][:int] (fun (i : int) -> i + 1 ) storage
Set.map_fold: forall 'a. forall 'acc. forall 'b. ('a -> 'acc -> 'b * 'acc) -> 'a set -> 'acc -> 'b set * 'acc
. Returns a list with the result of applying the function on each element of the list, plus an accumulator.type storage = int set val%view incr_storage storage (p : int) : int set * int = Set.map_fold[:int][:int][:int] (fun (acc : int) (i : int) -> i + acc, i + 1 ) storage 0
The Map
module¶
Maps are immutable data structures containing associations between keys (a comparable type) and values (any type). Since they are immutable, all modification primitives return a new updated map, and the map given in argument is unmodified.
Map.empty: forall 'key. forall 'elt. ('key, 'elt) map
. The empty map that binds elements of type'key
to elements of type'elt
.type storage = (int, bool) map val%entry restart storage d (p : unit) = let new_storage = Map.empty [:int] [:bool] in ([][:operation], new_storage)
Map.cardinal: forall 'key. forall 'elt. ('key, 'elt) map -> nat
. The number of bindings registered in a map.type storage = (int, bool) map val%view size_storage storage (p : unit) : nat = Map.cardinal [:int] [:bool] storage
Map.add: forall 'key. forall 'elt. 'key -> 'elt -> ('key, 'elt) map -> ('key, 'elt) map
. Binds a key to a value into a map, if the key is not present.type sign = Plus | Minus type storage = (int, sign) map val%entry add storage d (p : int) = let new_storage = if (p <[:int] 0) then Map.add [:int] [:sign] p Minus storage else Map.add [:int] [:sign] p Plus storage in ([][:operation], new_storage)
Map.remove: forall 'key. forall 'elt. 'key -> 'elt -> ('key, 'elt) map -> ('key, 'elt) map
. Removes a binding from a map, if present.type sign = Plus | Minus type storage = (int, sign) map val%entry remove storage d (p : int) = let new_storage = Map.remove [:int] [:sign] p storage in ([][:operation], new_storage)
Map.mem: forall 'key. forall 'map 'key -> ('key, 'elt) map -> bool
. Returnstrue
if the key belong to the map,false
otherwise.type sign = Plus | Minus type storage = (int, sign) map val%view exists storage (p : int) : bool = Map.mem [:int] [:sign] p storage
Map.find: forall 'key. forall 'map 'key -> ('key, 'elt) map -> 'elt option
. ReturnsSome elt
ifelt
is bound to the key in argument,None [:'elt]
otherwise.type sign = Plus | Minus type storage = (int, sign) map val%view get_elt storage (p : int) : sign option = Map.find [:int] [:sign] p storage
Map.iter: forall 'key. forall 'elt. ('elt -> 'key -> unit) -> ('key, 'elt) map -> unit
. Applies a function on all elements of the set. Since no value can be returned, it can only be used for side effects, i.e. to fail the transaction.exception Fail type sign = Plus | Minus type storage = (int, sign) map val%view check_storage storage (forbidden_val : int) : unit = Map.iter [:int] [:sign] (fun (elt : int) (_ : sign) -> if (elt =[:int] forbidden_val) then (raise Fail) [:unit]) storage
Map.fold: forall 'key. forall 'elt. forall 'acc. ('key -> 'elt -> 'acc -> 'acc) -> ('key, 'elt) map -> 'acc -> 'acc
. Iter on all elements of a set, while modifying an accumulator.type sign = Plus | Minus type storage = (int, sign) map val%view abs_sum storage (p : unit) : int = Map.fold [:int] [:sign] [:int] (fun (elt : int) (s : sign) (acc : int) -> match s with Plus -> acc + elt | Minus -> acc - elt ) storage 0
Map.map: forall 'key. forall 'elt. forall 'new_elt. ('key -> 'elt -> 'new_elt) -> ('key, 'elt) map -> ('key, 'new_elt) map
. Returns a list with the result of applying the function on each element of the list.type sign = Plus | Minus type storage = (int, sign) map val%entry reverse storage d (p : unit) = let new_storage = Map.map [:int] [:sign] [:sign] (fun (elt : int) (s : sign) -> match s with Plus -> Minus | Minus -> Plus ) storage in ([][:operation], new_storage)
Map.map_fold: forall 'key. forall 'elt. forall 'acc. forall 'new_elt. ('key -> 'elt -> 'acc -> 'new_elt * 'acc) -> ('key, 'elt) map -> 'acc -> ('key, 'new_elt) map * 'acc
. Returns a list with the result of applying the function on each element of the list, plus an accumulator.type sign = Plus | Minus type storage = (int, sign) map * int val%entry reverse storage d (p : unit) = let new_storage = Map.map_fold [:int] [:sign] [:int] [:sign] (fun (elt : int) (s : sign) (acc : int) -> match s with Plus -> Minus, acc + elt | Minus -> Plus, acc - elt ) storage.0 0 in ([][:operation], new_storage)
The BigMap
module¶
Big maps are a specific kind of maps, optimized for storing. They can be updated incrementally and scale to a high number of associations, whereas standard maps will have an expensive serialization and deserialization cost. You are limited by Michelson to one big map per smart contract, that should appear as the first element of the storage. Big maps cannot be iterated.
BigMap.empty<:TYPE, TYPE'>: (TYPE,TYPE') bigmap
. Returns the value associated with a key in the map. It is equivalent toGET
in Michelson.type storage = (int, address) bigmap val%entry reinit s d (p : unit) = ([][:operation], BigMap.empty<<int, address>>)
BigMap.add: forall 'key. forall 'val. 'key -> 'val -> ('key, 'val) big_map -> ('key, 'val) bigmap
Returns the big map in argument with the new binding
('key, 'val)
if'key
is not binded.
type storage = {last : int; addresses : (int, address) bigmap} val%entry add s d (p : address) = let new_storage = { last = s.last + 1; addresses = BigMap.add [:int] [:address] s.last p s.addresses } in ([][:operation], new_storage)
BigMap.remove: forall 'key. forall 'val. 'key -> ('key,'val) big_map -> ('key,'val) bigmap
. Returns the big map without the binding'key
.type storage = {last : int; addresses : (int, address) bigmap} val%entry add s d (p : int) = let new_storage = {s with addresses = BigMap.remove [:int][:address] p s.addresses} in ([][:operation], new_storage)
BigMap.mem: forall 'key. forall 'val. 'key -> ('key, 'val) bigmap -> bool
. Returnstrue
if an association exists in the big map for the key,false
otherwise.type storage = {last : int; addresses : (int, address) bigmap} val%view exists s (p : int) : bool = BigMap.mem [:int] [:address] p s.addresses
BigMap.find: forall 'key. forall 'val. 'key -> ('key,'val) bigmap -> 'val option
. ReturnsSome elt
if the argument is bound toelt
in the big map,None
otherwise.type storage = {last : int; addresses : (int, address) bigmap} exception Fail val%view get s (p : int) : address = match BigMap.find [:int] [:address] p s.addresses with Some a -> a | None -> (raise Fail) [:address]
The Current
module¶
Current.balance: unit -> dun
: returns the balance of the current contract. The balance contains the amount of dun that was sent by the current operation. It is equivalent toBALANCE
in Michelson.val%entry default storage d (p : unit) = let b = Current.balance () in ([][:operation], storage)
Current.time: unit -> timestamp
: returns the timestamp of the block in which the transaction is included. This value is chosen by the baker that is including the transaction, so it should not be used as a reliable source of alea. It is equivalent toNOW
in Michelson.type storage = unit val%entry default storage d (p : unit) = let b = Current.time () in ([][:operation], storage)
Current.amount: unit -> dun
: returns the amount of dun transferred by the current operation (standard or internal transaction). It is equivalent toAMOUNT
in Michelson.type storage = unit val%entry default storage d (p : unit) = let a = Current.amount () (* dun = a *) in ([][:operation], storage)
Current.gas: unit -> nat
: returns the amount of gas available to execute the rest of the transaction. It is equivalent toSTEPS_TO_QUOTA
in Michelson.type storage = unit val%entry default storage d (p : unit) = let a = Current.gas () in ([][:operation], storage)
Current.self: unit -> address
: returns the address of the current contract.type storage = address val%entry default storage d (p : unit) = let me = Current.self () in ([][:operation], me)
Current.source: unit -> address
: returns the address that initiated the current top-level transaction in the blockchain. It is the same one for all the transactions resulting from the top-level transaction, standard and internal. It is the address that paid the fees and storage cost, and signed the operation on the blockchain. It is equivalent toSOURCE
in Michelson.type storage = unit val%entry default storage d (p : unit) = let a = Current.source () in ([][:operation], storage)
Current.sender: unit -> address
: returns the address that initiated the current transaction. It is the same as the source for the top-level transaction, but it is the originating contract for internal operations. It is equivalent toSENDER
in Michelson.type storage = unit val%entry default storage d (p : unit) = let a = Current.sender () in ([][:operation], storage)
Current.cycle: unit -> nat
: returns the cycle in which the transaction initiating the execution of the current smart contract has been performed.type storage = nat val%entry default storage d (p : unit) = let now = Current.cycle () in ([][:operation], now)
Current.level: unit -> nat
: returns the level in which the transaction initiating the execution of the current smart contract has been performed.type storage = nat val%entry default storage d (p : unit) = let now = Current.level () in ([][:operation], now)
Current.blocks_per_cycle: unit -> nat
: returns the number of blocks per cycle (eg.4096p
on mainnet).Current.blocks_per_voting_period: unit -> nat
: returns the number of blocks per voting period (eg.4096p * 8 = 32768p
on mainnet).
The Voting
module¶
Voting.period: unit -> nat
: returns the current voting period number.Voting.total: unit -> nat
: returns the total number of rolls for the- current voting period.
Voting.position: unit -> nat
: returns the current levelL
within the- current voting period (
0 <= L < Current.block_per_voting_period ()
)
Voting.listed: keyhash -> bool
: returnstrue
if thekeyhash
has some- rolls in the current voting period, and
false
otherwise.
Voting.power: keyhash -> nat
: returns the number of rolls for a- particular
keyhash
in the current voting period. If the givenkeyhash
is not registered as a validator, the functions returns0p
.
The Contract
module¶
Contract.self<:CONTRACT TYPE> -> (instance CONTRACT TYPE) option
. Returns the current executing contract. If the contract does not matched the signature in argument, returnsNone
. It is equivalent toSELF
in Michelson.type storage = int contract type CT = sig val x : int end val x : int = 5 val%entry default storage d (() : unit) = let c = Contract.self<:CT> () in match c with None -> ([][:operation], storage) | Some (contract C : CT) -> ([][:operation], C.x)
Contract.at<:CONTRACT TYPE>: address -> (instance CONTRACT TYPE) option
. Returns the contract associated with the address. As forContract.self
, it must be annotated with the type of the contract.type storage = int contract type CT = sig val x : int end val%entry default storage d (k : address) = let c = Contract.at<:CT> k in match c with None -> ([][:operation], storage) | Some (contract C : CT) -> ([][:operation], C.x)
Contract.call: forall 'a. 'a entrypoint -> dun -> 'a -> operation
. Forges an internal contract call. It is equivalent toTRANSFER_TOKENS
in Michelson. The entry point name is optional (default
by default).type storage = unit contract type CT = sig val%entry default : int end val x : int = 5 val%entry default storage d (k : address) = let c = Contract.at<!CT> k in match c with None -> ([][:operation], storage) | Some (contract C : CT) -> ( let op = Contract.call [:int] C.default d x in ([op][:operation], storage) )
Contract.view: forall 'a. 'a view -> 'a
. Calls a view from a contract. Views does not initiate transaction when they are called, i.e. they are called in the contect of the calling contract, but with the storage of the target contract.Contract.view [:typ] view
deserializes the storage, which means that any change of the storage after is not taken into account.type storage = int contract type CT = sig type storage val%view storage_size : unit -> int end val%entry default storage d (k : address) = let c = Contract.at <:CT> k in match c with None -> ([][:operation], storage) | Some (contract C : CT) -> ( let size = Contract.view [:unit -> int] C.storage_size () in ([][:operation], storage) )
Contract.set_delegate: keyhash option -> operation
. Forge a delegation operation for the current contract. ANone
argument means that the contract should have no delegate (it falls back to its manager). The delegation operation will only be executed in an internal operation if it is returned at the end of the%entry
function. It is equivalent toSET_DELEGATE
in Michelson.type storage = unit val%entry default storage d (k : keyhash) = let op = Contract.set_delegate (Some k) in ([op][:operation], storage)
Contract.address: UnitContract instance -> address
. Returns the address of a contract. It is equivalent toADDRESS
in Michelson.type storage = unit val%entry default storage d (k : unit) = let c = Contract.self<<UnitContract>> () in let self_addr = Contract.address c in ([][:operation], storage)
Contract.create: forall 'a. keyhash option -> dun -> (sig type storage val%init storage : 'a end contract) ->'a -> (operation * address)
. Forges an operation to originate a contract with code. The contract is only created when the operation is executed, so it must be returned by the transaction. Note that the code must be specified as a contract structure (inlined or not).Contract.create manager_opt initial_amount (contract C) arg
forges an an origination operation for contract C with managermanager
, optional delegatedelegate
, initial balanceinitial_amount
and initial storageC.init arg
.Warning :
'a
must be a built-in type or a public alias of a built-in type.type storage = unit contract C = struct type storage = A | B val init (() : unit) : storage = A end val%entry default storage d (k : keyhash) = let (op, addr) = Contract.create [:unit] (Some k) d (contract C) () in ([op][:operation], storage)
The Account
module¶
Account.transfer: address -> dun -> operation
. Forges an internal transaction to the implicit (_i.e._ default) account contract in argument.type storage = int val%entry default storage d (k : address) = let op = Account.transfer k d in ([op][:operation], storage)
Account.default: keyhash -> instance UnitContract
. Returns the contract associated to the givenkeyhash
with an empty signature. It is equivalent toIMPLICIT_ACCOUNT
in Michelson.val get_contract (k : keyhash) : instance UnitContract = Account.default k
Account.manage: address -> int option -> bool -> address option -> address list -> operation
Returns an operation that updates the account informations. The operation will fail if the operation creator is not the administrator of the adress in argument.type info = (int option * bool * address option * address list) type storage = address val%entry manage storage d (info : info) = let manage_op = Account.manage storage info.0 info.1 info.2 info.3 in match manage_op with Some op -> ([op][:operation], storage) | None -> ([][:operation], storage)
Account.balance: address -> dun
Returns the amount of dun at a given address.type storage = (address, dun) map val%entry default storage d (k : address) = let amount = Account.balance k in ([][:operation], Map.add [:address] [:dun] k amount storage)
Account.is_revealed: keyhash -> bool
Returnstrue
if the givenkeyhash
’s public key is currently revealed, andfalse
otherwise.
The Crypto
module¶
Crypto.blake2b: bytes -> bytes
. Computes the cryptographic hash of a bytes with the cryptographic Blake2b function. It is equivalent toBLAKE2B
in Michelson.type storage = bytes val%entry default storage d (k : bytes) = let blakehash = Crypto.blake2b k in ([][:operation], blakehash)
Crypto.sha256: bytes -> bytes
. Computes the cryptographic hash of a bytes with the cryptographic Sha256 function. It is translated toSHA256
in Michelson.type storage = bytes val%entry default storage d (k : bytes) = let hash = Crypto.sha256 k in ([][:operation], hash)
Crypto.sha512: bytes -> bytes
. Computes the cryptographic hash of a bytes with the cryptographic Sha512 function. It is equivalent toSHA512
in Michelson.type storage = bytes val%entry default storage d (k : bytes) = let hash = Crypto.sha512 k in ([][:operation], hash)
Crypto.hash_key: key -> keyhash
. Hash a public key and encode the hash in B58check. It is equivalent toHASH_KEY
in Michelson.type storage = keyhash val%entry default storage d (k : key) = let kh = Crypto.hash_key k in ([][:operation], kh)
Crypto.check: key -> signature -> bytes -> bool
. Check that the signature corresponds to signing the (Blake2b hash of the) sequence of bytes with the public key. It is equivalent toCHECK_SIGNATURE
in Michelson. Signatures generated bydune-client sign bytes ...
can be checked this way.type data = abstract key * signature * bytes type storage = data list val%entry default storage d (k : data) = if Crypto.check k.0 k.1 k.2 then ([][:operation], k :: storage) else ([][:operation], storage)