Reviewing again the PascaLIGO contracts.

This commit is contained in:
Christian Rinderknecht 2020-02-27 19:09:14 +01:00
parent 93682629b4
commit a9214f864d
38 changed files with 209 additions and 216 deletions

View File

@ -7,7 +7,7 @@ let bad_contract basename =
let%expect_test _ =
run_ligo_good [ "measure-contract" ; contract "coase.ligo" ; "main" ] ;
[%expect {| 1747 bytes |}] ;
[%expect {| 1870 bytes |}] ;
run_ligo_good [ "measure-contract" ; contract "multisig.ligo" ; "main" ] ;
[%expect {| 1324 bytes |}] ;
@ -86,7 +86,9 @@ let%expect_test _ =
SWAP ;
DIP { DUP ; CAR ; CAR } ;
GET ;
IF_NONE { PUSH string "MAP FIND" ; FAILWITH } {} ;
IF_NONE
{ PUSH string "buy_single: No card pattern." ; FAILWITH }
{ DUP ; DIP { DROP } } ;
DUP ;
CAR ;
DIP { DUP ; CDR ; PUSH nat 1 ; ADD } ;
@ -159,7 +161,9 @@ let%expect_test _ =
SWAP ;
DIP { DUP ; CAR ; CDR } ;
GET ;
IF_NONE { PUSH string "MAP FIND" ; FAILWITH } {} ;
IF_NONE
{ PUSH string "sell_single: No card." ; FAILWITH }
{ DUP ; DIP { DROP } } ;
DUP ;
CAR ;
SENDER ;
@ -173,7 +177,9 @@ let%expect_test _ =
CDR ;
DIP { DIP 2 { DUP } ; DIG 2 ; CAR ; CAR } ;
GET ;
IF_NONE { PUSH string "MAP FIND" ; FAILWITH } {} ;
IF_NONE
{ PUSH string "sell_single: No card pattern." ; FAILWITH }
{ DUP ; DIP { DROP } } ;
DUP ;
DIP { DUP } ;
SWAP ;
@ -209,7 +215,9 @@ let%expect_test _ =
MUL ;
SENDER ;
CONTRACT unit ;
IF_NONE { PUSH string "bad address for get_contract" ; FAILWITH } {} ;
IF_NONE
{ PUSH string "sell_single: No contract." ; FAILWITH }
{ DUP ; DIP { DROP } } ;
DIP { DUP } ;
SWAP ;
DIP { DUP } ;
@ -246,7 +254,9 @@ let%expect_test _ =
CAR ;
DIP { DUP } ;
GET ;
IF_NONE { PUSH string "MAP FIND" ; FAILWITH } {} ;
IF_NONE
{ PUSH string "transfer_single: No card." ; FAILWITH }
{ DUP ; DIP { DROP } } ;
DUP ;
CAR ;
SENDER ;

View File

@ -144,7 +144,7 @@ module Simplify = struct
| "Bytes.unpack" -> ok C_BYTES_UNPACK
| "bytes_unpack" -> ok C_BYTES_UNPACK (* Deprecated *)
| "Bytes.length" -> ok C_SIZE
| "Bytes.size" -> ok C_SIZE
| "Bytes.size" -> ok C_SIZE (* Deprecated *)
| "bytes_concat" -> ok C_CONCAT (* Deprecated *)
| "Bytes.concat" -> ok C_CONCAT
| "Bytes.slice" -> ok C_SLICE
@ -165,7 +165,8 @@ module Simplify = struct
(* Set module *)
| "Set.size" -> ok C_SIZE
| "Set.cardinal" -> ok C_SIZE
| "Set.size" -> ok C_SIZE (* Deprecated *)
| "set_size" -> ok C_SIZE (* Deprecated *)
| "set_empty" -> ok C_SET_EMPTY (* Deprecated *)
| "Set.mem" -> ok C_SET_MEM
@ -346,7 +347,8 @@ module Simplify = struct
| "Set.add" -> ok C_SET_ADD
| "Set.remove" -> ok C_SET_REMOVE
| "Set.fold" -> ok C_SET_FOLD
| "Set.size" -> ok C_SIZE
| "Set.size" -> ok C_SIZE (* Deprecated *)
| "Set.cardinal" -> ok C_SIZE
(* Map module *)

View File

@ -1,5 +1,3 @@
// function main (const c : contract (unit)) : address is address (c)
function main (const p : key_hash) : address is block {
const c : contract (unit) = implicit_account (p);
} with address (c)
const c : contract (unit) = Tezos.implicit_account (p);
} with Tezos.address (c)

View File

@ -1,8 +1,5 @@
function check (const p : unit) : int is
block {
var result : int := 0;
if Tezos.amount = 100tz then
result := 42
else
result := 0
if amount = 100tz then result := 42 else result := 0
} with result

View File

@ -1 +1 @@
let check = if Tezos.amount > 100tez then 42 else 0
let check_ (p : unit) : int = if Tezos.amount = 100tz then 42 else 0

View File

@ -1,15 +1,9 @@
// Test PascaLIGO arithmetic operators
function mod_op (const n : int) : nat is n mod 42
function plus_op (const n : int) : int is n + 42
function minus_op (const n : int) : int is n - 42
function times_op (const n : int) : int is n * 42
function div_op (const n : int) : int is n / 2
function int_op (const n : nat) : int is int (n)
function neg_op (const n : int) : int is -n

View File

@ -1,4 +1 @@
function main (const i : int) : int is
block {
i := i + 1
} with i
function main (const i : int) : int is block {i := i + 1} with i

View File

@ -9,4 +9,4 @@ type storage is tez
type return is list (operation) * storage
function main (const param : parameter; const store: storage) : return is
((nil : list (operation)), balance)
((nil : list (operation)), Tezos.balance)

View File

@ -22,8 +22,6 @@ function rm (var m : foo) : foo is block {
remove 42 from map m
} with m
function gf (const m : foo) : int is get_force (23, m)
function get (const m : foo) : option (int) is m[42]
const empty_big_map : big_map (int,int) = big_map []

View File

@ -1,11 +1,5 @@
// Test PascaLIGO boolean operators
function or_true (const b : bool) : bool is b or True
function or_false (const b : bool) : bool is b or False
function and_true (const b : bool) : bool is b and True
function and_false (const b : bool) : bool is b and False
function not_bool (const b : bool) : bool is not b

View File

@ -1,5 +1,3 @@
function concat_op (const s : bytes) : bytes is bytes_concat (s, 0x7070)
function slice_op (const s : bytes) : bytes is bytes_slice (1n, 2n, s)
function hasherman (const s : bytes) : bytes is sha_256 (s)
function concat_op (const s : bytes) : bytes is Bytes.concat (s, 0x7070)
function slice_op (const s : bytes) : bytes is Bytes.sub (1n, 2n, s)
function hasherman (const s : bytes) : bytes is Crypto.sha256 (s)

View File

@ -1,11 +1,11 @@
function id_string (const p : string) : option (string) is block {
const packed : bytes = bytes_pack (p)
} with (bytes_unpack (packed) : option (string))
const packed : bytes = Bytes.pack (p)
} with (Bytes.unpack (packed) : option (string))
function id_int (const p : int) : option (int) is block {
const packed : bytes = bytes_pack (p)
} with (bytes_unpack (packed) : option (int))
const packed : bytes = Bytes.pack (p)
} with (Bytes.unpack (packed) : option (int))
function id_address (const p : address) : option (address) is block {
const packed : bytes = bytes_pack (p)
} with (bytes_unpack (packed) : option (address))
const packed : bytes = Bytes.pack (p)
} with (Bytes.unpack (packed) : option (address))

View File

@ -1 +1 @@
function chain_id (const tt : chain_id) : chain_id is get_chain_id
function chain_id (const tt : chain_id) : chain_id is Tezos.chain_id

View File

@ -1,4 +1,4 @@
function check_signature (const pk : key;
const signed : signature;
const msg : bytes) : bool
is crypto_check (pk, signed, msg)
is Crypto.check (pk, signed, msg)

View File

@ -45,27 +45,38 @@ type parameter is
| Transfer_single of action_transfer_single
function transfer_single (const action : action_transfer_single;
const s : storage) : return is block {
const s : storage) : return is
block {
const cards : cards = s.cards;
const card : card = get_force (action.card_to_transfer, cards);
const card : card =
case cards[action.card_to_transfer] of
Some (card) -> card
| None -> (failwith ("transfer_single: No card.") : card)
end;
if card.card_owner =/= sender then
failwith ("This card doesn't belong to you")
else skip;
card.card_owner := action.destination;
cards[action.card_to_transfer] := card;
s.cards := cards;
const operations : list (operation) = nil
} with (operations, s)
s.cards := cards
} with ((nil : list (operation)), s)
function sell_single (const action : action_sell_single;
const s : storage) : return is
block {
const card : card = get_force (action.card_to_sell, s.cards);
const card : card =
case s.cards[action.card_to_sell] of
Some (card) -> card
| None -> (failwith ("sell_single: No card.") : card)
end;
if card.card_owner =/= sender
then failwith ("This card doesn't belong to you")
else skip;
const card_pattern : card_pattern =
get_force (card.card_pattern, s.card_patterns);
case s.card_patterns[card.card_pattern] of
Some (pattern) -> pattern
| None -> (failwith ("sell_single: No card pattern.") : card_pattern)
end;
card_pattern.quantity := abs (card_pattern.quantity - 1n);
const card_patterns : card_patterns = s.card_patterns;
card_patterns[card.card_pattern] := card_pattern;
@ -74,8 +85,12 @@ function sell_single (const action : action_sell_single;
remove action.card_to_sell from map cards;
s.cards := cards;
const price : tez = card_pattern.coefficient * card_pattern.quantity;
const receiver : contract (unit) = get_contract (sender);
const op : operation = transaction (unit, price, receiver);
const receiver : contract (unit) =
case (Tezos.get_contract_opt (Tezos.sender) : option (contract (unit))) of
Some (contract) -> contract
| None -> (failwith ("sell_single: No contract.") : contract (unit))
end;
const op : operation = Tezos.transaction (unit, price, receiver);
const operations : list (operation) = list [op]
} with (operations, s)
@ -84,12 +99,13 @@ function buy_single (const action : action_buy_single;
block {
// Check funds
const card_pattern : card_pattern =
get_force (action.card_to_buy, s.card_patterns);
case s.card_patterns[action.card_to_buy] of
Some (pattern) -> pattern
| None -> (failwith ("buy_single: No card pattern.") : card_pattern)
end;
const price : tez =
card_pattern.coefficient * (card_pattern.quantity + 1n);
if price > amount then failwith ("Not enough money") else skip;
// Administrative procedure
const operations : list(operation) = nil;
// Increase quantity
card_pattern.quantity := card_pattern.quantity + 1n;
const card_patterns : card_patterns = s.card_patterns;
@ -103,7 +119,7 @@ function buy_single (const action : action_buy_single;
];
s.cards := cards;
s.next_id := s.next_id + 1n
} with (operations, s)
} with ((nil : list (operation)), s)
function main (const action : parameter; const s : storage) : return is
case action of

View File

@ -1,4 +1,4 @@
type integer is int
type integer = int
let main (i : int) =
if (i = 2 : bool) then (42 : int) else (0 : integer)

View File

@ -1,5 +1,3 @@
(* TODO : make a test using mutation, not shadowing *)
let main (i : int) =
let result = 0 in
if i = 2 then

View File

@ -1,3 +1,2 @@
function hasherman512 (const s: bytes) : bytes is sha_512 (s)
function hasherman_blake (const s: bytes) : bytes is blake2b (s)
function hasherman512 (const s : bytes) : bytes is Crypto.sha512 (s)
function hasherman_blake (const s : bytes) : bytes is Crypto.blake2b (s)

View File

@ -1,5 +1,3 @@
// Test PascaLIGO top-level declarations
const foo : int = 42
function main (const i : int) : int is i + foo

View File

@ -26,4 +26,7 @@ type nested_record_t is
function nested_record (var nee : nested_record_t) : string is
block {
nee.nesty.mymap[1] := "one"
} with get_force (1, nee.nesty.mymap)
} with case nee.nesty.mymap[1] of
Some (s) -> s
| None -> (failwith ("Should not happen.") : string)
end

View File

@ -7,7 +7,6 @@ type storage is int
type return is list (operation) * storage
function increment (const i : int; const n : int) : int is i+n
function decrement (const i : int; const n : int) : int is i-n
const nop : list (operation) = nil

View File

@ -4,9 +4,12 @@ type return is list (operation) * storage
function cb (const a : address; const s : storage) : return is
block {
const c : contract (unit) = get_entrypoint ("%cb", a)
}
with (list [transaction (unit, 0mutez, c)], s)
const c : contract (unit) =
case (Tezos.get_entrypoint_opt ("%cb", a) : option (contract (unit))) of
Some (contract) -> contract
| None -> (failwith ("cb: Entrypoint not found.") : contract (unit))
end
} with (list [Tezos.transaction (unit, 0tez, c)], s)
function cbo (const a : address; const s : storage) : return is
@ -14,6 +17,6 @@ function cbo (const a : address; const s : storage) : return is
const c : contract (unit) =
case (get_entrypoint_opt ("%cbo", a) : option (contract (unit))) of
Some (c) -> c
| None -> (failwith ("entrypoint not found") : contract (unit))
| None -> (failwith ("cbo: Entrypoint not found.") : contract (unit))
end
} with (list [transaction(unit, 0mutez, c)], s)
} with (list [Tezos.transaction (unit, 0tez, c)], s)

View File

@ -1,4 +1,4 @@
type storage = unit
let main (p : unit; store : storage) : operation list * storage =
if true then failwith "This contract always fails"
let main (p, store : unit * storage) : operation list * storage =
failwith "This contract always fails"

View File

@ -1,19 +1,20 @@
type storage is unit
type return is list (operation) * storage
function cb (const s : storage) : return is
block {
const c : contract(unit) = get_contract(sender)
}
with (list [transaction(unit, 0mutez, c)], s)
function cb (const s : storage) : return is block {
const c : contract (unit) =
case (Tezos.get_contract_opt (Tezos.sender) : option (contract (unit))) of
Some (contract) -> contract
| None -> (failwith ("cb: No contract.") : contract (unit))
end
} with (list [Tezos.transaction (unit, 0tez, c)], s)
function cbo (const s : unit) : return is
block {
const c : contract (unit) =
case (get_contract_opt(sender) : option(contract(unit))) of
Some (c) -> c
case (Tezos.get_contract_opt (Tezos.sender) : option (contract (unit))) of
Some (contract) -> contract
| None -> (failwith ("contract not found") : contract (unit))
end
}
with (list [transaction(unit, 0mutez, c)], s)
} with (list [Tezos.transaction (unit, 0tez, c)], s)

View File

@ -10,8 +10,12 @@ function get_top (const h : heap) : heap_elt is get_force (1n, h)
function pop_switch (const h : heap) : heap is
block {
const result : heap_elt = get_top (h);
const s : nat = size (h);
const last : heap_elt = get_force (s, h);
const s : nat = Map.size (h);
const last : heap_elt =
case h[s] of
Some (e) -> e
| None -> (failwith ("No element.") : heap_elt)
end;
remove 1n from map h;
h[1n] := last
} with h
@ -19,8 +23,12 @@ function pop_switch (const h : heap) : heap is
function pop_ (const h : heap) : nat is
block {
const result : heap_elt = get_top (h);
const s : nat = size (h);
var current : heap_elt := get_force (s, h);
const s : nat = Map.size (h);
var current : heap_elt :=
case h[s] of
Some (e) -> e
| None -> (failwith ("No element.") : heap_elt)
end;
const i : nat = 1n;
const left : nat = 2n * i;
const right : nat = left + 1n;

View File

@ -1 +1,2 @@
function main (const kh: key_hash) : contract (unit) is implicit_account (kh)
function main (const kh: key_hash) : contract (unit) is
Tezos.implicit_account (kh)

View File

@ -1,7 +1,5 @@
function check_hash_key (const kh1 : key_hash;
const k2 : key) : bool * key_hash is
block {
var ret : bool := False;
var kh2 : key_hash := crypto_hash_key (k2);
if kh1 = kh2 then ret := True else skip
} with (ret, kh2)
var kh2 : key_hash := Crypto.hash_key (k2);
} with ((kh1 = kh2), kh2)

View File

@ -1,8 +1,9 @@
type storage is record
type storage is record [
one : map (key_hash, nat);
two: big_map(key_hash, bool);
end
two : big_map (key_hash, bool)
]
type return is list (operation) * storage
function main (const a : int; const store : storage) : return is ((nil: list(operation)), store)
function main (const a : int; const store : storage) : return is
((nil : list (operation)), store)

View File

@ -17,17 +17,17 @@ const bl : foobar = list [144; 51; 42; 120; 421]
function fold_op (const s : list (int)) : int is
block {
function aggregate (const prec: int; const cur: int) : int is prec+cur
} with list_fold (aggregate, s, 10)
} with List.fold (aggregate, s, 10)
function iter_op (const s : list (int)) : int is
block {
var r : int := 0;
function aggregate (const i : int) : unit is
block { r := r + i } with unit;
list_iter (aggregate, s)
List.iter (aggregate, s)
} with r
function map_op (const s : list (int)) : list (int) is
block {
function increment (const i : int) : int is i+1
} with list_map (increment, s)
} with List.map (increment, s)

View File

@ -1,6 +1,6 @@
function shadowing_in_body (var nee : unit) : string is block {
var st : string := "";
var list1 : list(string) := list "to"; "to" end;
var list1 : list (string) := list ["to"; "to"];
for x in list list1 block {
const x : string = "ta";
st := st ^ x;
@ -10,7 +10,7 @@ function shadowing_in_body (var nee : unit) : string is block {
function shadowing_assigned_in_body (var nee : unit) : string is block {
var st : string := "";
var list1 : list(string) := list "to"; "to" end;
var list1 : list (string) := list ["to"; "to"];
for x in list list1 block {
st := st ^ x;
var st : string := "ta";

View File

@ -30,32 +30,28 @@ function patch_ (var m : foobar) : foobar is block {
function patch_deep (var m : foobar * nat) : foobar * nat is
block { patch m.0 with map [1 -> 9] } with m
function size_ (const m : foobar) : nat is size (m)
function gf (const m : foobar) : int is get_force (23, m)
function size_ (const m : foobar) : nat is Map.size (m)
function get (const m : foobar) : option (int) is m[42]
function get_ (const m : foobar) : option (int) is map_get (42, m)
function mem (const k: int; const m: foobar) : bool is map_mem (k, m)
function mem (const k: int; const m: foobar) : bool is Map.mem (k, m)
function iter_op (const m : foobar) : unit is
block {
function aggregate (const i : int; const j : int) : unit is block
{ if i=j then skip else failwith ("fail") } with unit
} with map_iter (aggregate, m)
} with Map.iter (aggregate, m)
function map_op (const m : foobar) : foobar is
block {
function increment (const i : int; const j : int) : int is j+1
} with map_map (increment, m)
} with Map.map (increment, m)
function fold_op (const m : foobar) : int is
block {
function aggregate (const i : int; const j : int * int) : int is
i + j.0 + j.1
} with map_fold(aggregate, m, 10)
} with Map.fold (aggregate, m, 10)
function deep_op (var m : foobar) : foobar is
block {

View File

@ -37,22 +37,22 @@ function send (const param : send_pt; const s : storage) : return is
block {
// check sender against the authorized addresses
if not set_mem (sender, s.authorized_addresses)
if not Set.mem (Tezos.sender, s.authorized_addresses)
then failwith("Unauthorized address")
else skip;
// check message size against the stored limit
var message : message := param;
const packed_msg : bytes = bytes_pack (message);
if size (packed_msg) > s.max_message_size
const packed_msg : bytes = Bytes.pack (message);
if Bytes.length (packed_msg) > s.max_message_size
then failwith ("Message size exceed maximum limit")
else skip;
(* compute the new set of addresses associated with the message and
update counters *)
var new_store : addr_set := set_empty;
var new_store : addr_set := set [];
case map_get (packed_msg, s.message_store) of
Some (voters) ->
@ -60,26 +60,25 @@ function send (const param : send_pt; const s : storage) : return is
(* The message is already stored.
Increment the counter only if the sender is not already
associated with the message. *)
if set_mem (sender, voters)
if Set.mem (Tezos.sender, voters)
then skip
else s.proposal_counters[sender] :=
get_force (sender, s.proposal_counters) + 1n;
new_store := set_add(sender,voters)
else s.proposal_counters[Tezos.sender] :=
get_force (Tezos.sender, s.proposal_counters) + 1n;
new_store := Set.add (Tezos.sender,voters)
}
| None ->
block {
// the message has never been received before
s.proposal_counters[sender] :=
get_force (sender, s.proposal_counters) + 1n;
new_store := set [sender]
get_force (Tezos.sender, s.proposal_counters) + 1n;
new_store := set [Tezos.sender]
}
end;
// check sender counters against the maximum number of proposal
var sender_proposal_counter : nat :=
get_force (sender, s.proposal_counters);
get_force (Tezos.sender, s.proposal_counters);
if sender_proposal_counter > s.max_proposal
then failwith ("Maximum number of proposal reached")
@ -89,14 +88,14 @@ function send (const param : send_pt; const s : storage) : return is
var ret_ops : list (operation) := nil;
if size (new_store) >= s.threshold then {
if Set.cardinal (new_store) >= s.threshold then {
remove packed_msg from map s.message_store;
ret_ops := message (s.state_hash);
// update the state hash
s.state_hash := sha_256 (bytes_concat (s.state_hash, packed_msg));
s.state_hash := Crypto.sha256 (Bytes.concat (s.state_hash, packed_msg));
// decrement the counters
for addr -> ctr in map s.proposal_counters block {
if set_mem(addr,new_store) then
if Set.mem (addr, new_store) then
s.proposal_counters[addr] := abs (ctr - 1n)
else skip
}
@ -106,26 +105,26 @@ function send (const param : send_pt; const s : storage) : return is
function withdraw (const param : withdraw_pt; const s : storage) : return is
block {
var message : message := param;
const packed_msg : bytes = bytes_pack (message);
const packed_msg : bytes = Bytes.pack (message);
case map_get(packed_msg, s.message_store) of
case s.message_store[packed_msg] of
Some (voters) ->
block {
// The message is stored
const new_set : addr_set = set_remove (sender, voters);
const new_set : addr_set = Set.remove (Tezos.sender, voters);
(* Decrement the counter only if the sender was already
associated with the message *)
if size (voters) =/= size (new_set)
then s.proposal_counters[sender] :=
abs (get_force (sender, s.proposal_counters) - 1n)
if Set.cardinal (voters) =/= Set.cardinal (new_set)
then s.proposal_counters[Tezos.sender] :=
abs (get_force (Tezos.sender, s.proposal_counters) - 1n)
else skip;
(* If the message is left without any associated addresses,
remove the corresponding message_store field *)
if size (new_set) = 0n
if Set.cardinal (new_set) = 0n
then remove packed_msg from map s.message_store
else s.message_store[packed_msg] := new_set
}

View File

@ -38,7 +38,7 @@ function check_message (const param : check_message_pt;
failwith ("Counters does not match")
else {
const packed_payload : bytes =
bytes_pack ((message, param.counter, s.id, get_chain_id));
Bytes.pack ((message, param.counter, s.id, Tezos.chain_id));
var valid : nat := 0n;
var keys : authorized_keys := s.auth;
@ -47,8 +47,8 @@ function check_message (const param : check_message_pt;
nil -> skip
| key # tl -> block {
keys := tl;
if pkh_sig.0 = crypto_hash_key (key) then
if crypto_check (key, pkh_sig.1, packed_payload)
if pkh_sig.0 = Crypto.hash_key (key) then
if Crypto.check (key, pkh_sig.1, packed_payload)
then valid := valid + 1n
else failwith ("Invalid signature")
else skip

View File

@ -1019,21 +1019,11 @@ let map_ type_f path : unit result =
let make_expected = e_nat in
expect_eq_n_strict_pos_small program "size_" make_input make_expected
in
let%bind () =
let make_input = fun n -> ez [(23, n) ; (42, 4)] in
let make_expected = e_int in
expect_eq_n program "gf" make_input make_expected
in
let%bind () =
let make_input = fun n -> ez [(23, n) ; (42, 4)] in
let make_expected = fun _ -> e_some @@ e_int 4 in
expect_eq_n program "get" make_input make_expected
in
let%bind () =
let make_input = fun n -> ez [(23, n) ; (42, 4)] in
let make_expected = fun _ -> e_some @@ e_int 4 in
expect_eq_n program "get_" make_input make_expected
in
let%bind () =
let input_map = ez [(23, 10) ; (42, 4)] in
expect_eq program "mem" (e_tuple [(e_int 23) ; input_map]) (e_bool true)
@ -1081,11 +1071,6 @@ let big_map_ type_f path : unit result =
let lst' = List.map (fun (x, y) -> e_int x, e_int y) lst in
(e_typed_big_map lst' t_int t_int)
in
let%bind () =
let make_input = fun n -> ez [(23, n) ; (42, 4)] in
let make_expected = e_int in
expect_eq_n program "gf" make_input make_expected
in
let%bind () =
let make_input = fun n ->
let m = ez [(23 , 0) ; (42 , 0)] in