Contract factories and bytecode introspection (#305)

* Support for CREATE, CLONE and BYTECODE_HASH

* Add missing files

* Pushed the clone example through the typechecker

* CLONE compiles

* Fix dependent type in CLONE

* Bytecode hash fixes

* Refactor

* Refactor 2

* move some logic away

* Fixed some error messages. Type inference of child contract still does some random shit\n(mistakes arguments with result type)

* CREATE sometimes compiles and sometimes not

* Fix some scoping/constraint issues

* works, needs cleanup

* cleanup

* Fix some tests. Remove optimization of singleton tuples

* Fix default argument for clone

* Cleanup

* CHANGELOG

* Mention void type

* Address review, fix some dialyzer errors

* Please dialyzer

* Fix failing tests

* Write negative tests

* Docs

* TOC

* missing 'the'

* missing 'the'

* missing 'the'

* missing 'the'

* mention pre-fund

* format

* pre-fund clarification

* format

* Grammar in docs
This commit is contained in:
Radosław Rowicki
2021-05-18 12:21:57 +02:00
committed by GitHub
parent d82b42518e
commit 1d9f59fec3
68 changed files with 1113 additions and 494 deletions
+1 -1
View File
@@ -190,7 +190,7 @@ parameterized_contract(ExtraCode, FunName, Types) ->
lists:flatten(
["contract Remote =\n"
" entrypoint bla : () => unit\n\n"
"contract Dummy =\n",
"main contract Dummy =\n",
ExtraCode, "\n",
" type an_alias('a) = string * 'a\n"
" record r = {x : an_alias(int), y : variant}\n"
+53 -44
View File
@@ -22,7 +22,8 @@ test_cases(1) ->
MapACI = #{contract =>
#{name => <<"C">>,
type_defs => [],
payable => true,
payable => true,
kind => contract_main,
functions =>
[#{name => <<"a">>,
arguments =>
@@ -31,56 +32,57 @@ test_cases(1) ->
returns => <<"int">>,
stateful => true,
payable => true}]}},
DecACI = <<"payable contract C =\n"
DecACI = <<"payable main contract C =\n"
" payable entrypoint a : (int) => int\n">>,
{Contract,MapACI,DecACI};
test_cases(2) ->
Contract = <<"contract C =\n"
Contract = <<"main contract C =\n"
" type allan = int\n"
" entrypoint a(i : allan) = i+1\n">>,
MapACI = #{contract =>
#{name => <<"C">>, payable => false,
type_defs =>
[#{name => <<"allan">>,
typedef => <<"int">>,
vars => []}],
functions =>
[#{arguments =>
[#{name => <<"i">>,
type => <<"C.allan">>}],
name => <<"a">>,
returns => <<"int">>,
stateful => false,
payable => false}]}},
DecACI = <<"contract C =\n"
#{name => <<"C">>, payable => false,
kind => contract_main,
type_defs =>
[#{name => <<"allan">>,
typedef => <<"int">>,
vars => []}],
functions =>
[#{arguments =>
[#{name => <<"i">>,
type => <<"C.allan">>}],
name => <<"a">>,
returns => <<"int">>,
stateful => false,
payable => false}]}},
DecACI = <<"main contract C =\n"
" type allan = int\n"
" entrypoint a : (C.allan) => int\n">>,
{Contract,MapACI,DecACI};
test_cases(3) ->
Contract = <<"contract C =\n"
Contract = <<"main contract C =\n"
" type state = unit\n"
" datatype event = SingleEventDefined\n"
" datatype bert('a) = Bin('a)\n"
" entrypoint a(i : bert(string)) = 1\n">>,
" datatype bert('a) = Bin('a)\n"
" entrypoint a(i : bert(string)) = 1\n">>,
MapACI = #{contract =>
#{functions =>
[#{arguments =>
[#{name => <<"i">>,
type =>
#{<<"C.bert">> => [<<"string">>]}}],
name => <<"a">>,returns => <<"int">>,
stateful => false, payable => false}],
name => <<"C">>, payable => false,
event => #{variant => [#{<<"SingleEventDefined">> => []}]},
state => <<"unit">>,
[#{arguments =>
[#{name => <<"i">>,
type =>
#{<<"C.bert">> => [<<"string">>]}}],
name => <<"a">>,returns => <<"int">>,
stateful => false, payable => false}],
name => <<"C">>, payable => false, kind => contract_main,
event => #{variant => [#{<<"SingleEventDefined">> => []}]},
state => <<"unit">>,
type_defs =>
[#{name => <<"bert">>,
typedef =>
#{variant =>
[#{<<"Bin">> => [<<"'a">>]}]},
vars => [#{name => <<"'a">>}]}]}},
DecACI = <<"contract C =\n"
[#{name => <<"bert">>,
typedef =>
#{variant =>
[#{<<"Bin">> => [<<"'a">>]}]},
vars => [#{name => <<"'a">>}]}]}},
DecACI = <<"main contract C =\n"
" type state = unit\n"
" datatype event = SingleEventDefined\n"
" datatype bert('a) = Bin('a)\n"
@@ -101,17 +103,24 @@ aci_test_contract(Name) ->
true -> [debug_mode];
false -> []
end ++ [{include, {file_system, [aeso_test_utils:contract_path()]}}],
{ok, JSON} = aeso_aci:contract_interface(json, String, Opts),
{ok, #{aci := JSON1}} = aeso_compiler:from_string(String, [{aci, json}, {backend, fate} | Opts]),
?assertEqual(JSON, JSON1),
JSON = case aeso_aci:contract_interface(json, String, Opts) of
{ok, J} -> J;
{error, ErrorStringJ} when is_binary(ErrorStringJ) -> error(ErrorStringJ);
{error, ErrorJ} -> aeso_compiler_tests:print_and_throw(ErrorJ)
end,
case aeso_compiler:from_string(String, [{aci, json}, {backend, fate} | Opts]) of
{ok, #{aci := JSON1}} ->
?assertEqual(JSON, JSON1),
io:format("JSON:\n~p\n", [JSON]),
{ok, ContractStub} = aeso_aci:render_aci_json(JSON),
io:format("JSON:\n~p\n", [JSON]),
{ok, ContractStub} = aeso_aci:render_aci_json(JSON),
io:format("STUB:\n~s\n", [ContractStub]),
check_stub(ContractStub, [{src_file, Name}]),
io:format("STUB:\n~s\n", [ContractStub]),
check_stub(ContractStub, [{src_file, Name}]),
ok.
ok;
{error, ErrorString} when is_binary(ErrorString) -> error(ErrorString);
{error, Error} -> aeso_compiler_tests:print_and_throw(Error)
end.
check_stub(Stub, Options) ->
try aeso_parser:string(binary_to_list(Stub), Options) of
+2 -2
View File
@@ -59,8 +59,8 @@ calldata_aci_test_() ->
end} || {ContractName, Fun, Args} <- compilable_contracts()].
parse_args(Fun, Args) ->
[{contract, _, _, [{letfun, _, _, _, _, {app, _, _, AST}}]}] =
aeso_parser:string("contract Temp = function foo() = " ++ Fun ++ "(" ++ string:join(Args, ", ") ++ ")"),
[{contract_main, _, _, [{letfun, _, _, _, _, {app, _, _, AST}}]}] =
aeso_parser:string("main contract Temp = function foo() = " ++ Fun ++ "(" ++ string:join(Args, ", ") ++ ")"),
strip_ann(AST).
strip_ann(T) when is_tuple(T) ->
+68 -26
View File
@@ -34,9 +34,7 @@ simple_compile_test_() ->
#{fate_code := Code} when Backend == fate ->
Code1 = aeb_fate_code:deserialize(aeb_fate_code:serialize(Code)),
?assertMatch({X, X}, {Code1, Code});
ErrBin ->
io:format("\n~s", [ErrBin]),
error(ErrBin)
Error -> io:format("\n\n~p\n\n", [Error]), print_and_throw(Error)
end
end} || ContractName <- compilable_contracts(), Backend <- [aevm, fate],
not lists:member(ContractName, not_compilable_on(Backend))] ++
@@ -179,17 +177,16 @@ compilable_contracts() ->
"lhs_matching",
"more_strings",
"protected_call",
"hermetization_turnoff"
"hermetization_turnoff",
"multiple_contracts",
"clone",
"clone_simple",
"create",
"test" % Custom general-purpose test file. Keep it last on the list.
].
not_compilable_on(fate) -> [];
not_compilable_on(aevm) ->
[ "stdlib_include", "manual_stdlib_include", "pairing_crypto"
, "aens_update", "basic_auth_tx", "more_strings"
, "unapplied_builtins", "bytes_to_x", "state_handling", "protected_call"
, "hermetization_turnoff"
].
not_compilable_on(aevm) -> compilable_contracts().
debug_mode_contracts() ->
["hermetization_turnoff"].
@@ -635,9 +632,9 @@ failing_contracts() ->
<<?Pos(2, 1)
"Cannot compile with this version of the compiler,\n"
"because it does not satisfy the constraint ", Version/binary, " == 9.9.9">>])
, ?TYPE_ERROR(multiple_contracts,
, ?TYPE_ERROR(interface_with_defs,
[<<?Pos(2, 3)
"Only the main contract can contain defined functions or entrypoints.\n"
"Contract interfaces cannot contain defined functions or entrypoints.\n"
"Fix: replace the definition of 'foo' by a type signature.">>])
, ?TYPE_ERROR(contract_as_namespace,
[<<?Pos(5, 28)
@@ -733,6 +730,39 @@ failing_contracts() ->
, ?TYPE_ERROR(bad_state,
[<<?Pos(4, 16)
"Conflicting updates for field 'foo'">>])
, ?TYPE_ERROR(factories_type_errors,
[<<?Pos(10,18)
"Chain.clone requires `ref` named argument of contract type.">>,
<<?Pos(11,18)
"Cannot unify (gas : int, value : int, protected : bool) => if(protected, option(void), void)\n and (gas : int, value : int, protected : bool, int, bool) => 'b\n"
"when checking contract construction of type\n (gas : int, value : int, protected : bool) =>\n if(protected, option(void), void) (at line 11, column 18)\nagainst the expected type\n (gas : int, value : int, protected : bool, int, bool) => 'b">>,
<<?Pos(12,37)
"Cannot unify int\n and bool\n"
"when checking named argument\n gas : int\nagainst inferred type\n bool">>,
<<?Pos(13,18),
"Kaboom is not implemented.\n"
"when resolving arguments of variadic function\n Chain.create">>,
<<?Pos(18,18)
"Cannot unify (gas : int, value : int, protected : bool, int, bool) => if(protected, option(void), void)\n and (gas : int, value : int, protected : bool) => 'a\n"
"when checking contract construction of type\n (gas : int, value : int, protected : bool, int, bool) =>\n if(protected, option(void), void) (at line 18, column 18)\nagainst the expected type\n (gas : int, value : int, protected : bool) => 'a">>,
<<?Pos(19,42),
"Named argument protected (at line 19, column 42) is not one of the expected named arguments\n - value : int">>,
<<?Pos(20,42),
"Cannot unify int\n and bool\n"
"when checking named argument\n value : int\nagainst inferred type\n bool">>
])
, ?TYPE_ERROR(ambiguous_main,
[<<?Pos(1,1)
"Could not deduce the main contract. You can point it out manually with the `main` keyword.">>
])
, ?TYPE_ERROR(no_main_contract,
[<<?Pos(0,0)
"No contract defined.">>
])
, ?TYPE_ERROR(multiple_main_contracts,
[<<?Pos(1,6)
"Only one main contract can be defined.">>
])
].
-define(Path(File), "code_errors/" ??File).
@@ -746,9 +776,7 @@ failing_contracts() ->
{fate, ?Msg(File, Line, Col, ErrFATE)}]}).
failing_code_gen_contracts() ->
[ ?SAME(last_declaration_must_be_contract, 1, 1,
"Expected a contract as the last declaration instead of the namespace 'LastDeclarationIsNotAContract'")
, ?SAME(missing_definition, 2, 14,
[ ?SAME(missing_definition, 2, 14,
"Missing definition of function 'foo'.")
, ?AEVM(polymorphic_entrypoint, 2, 17,
"The argument\n"
@@ -846,6 +874,8 @@ failing_code_gen_contracts() ->
"Invalid state type\n"
" {f : (int) => int}\n"
"The state cannot contain functions in the AEVM. Use FATE if you need this.")
, ?FATE(child_with_decls, 2, 14,
"Missing definition of function 'f'.")
].
validation_test_() ->
@@ -883,14 +913,26 @@ validation_fails() ->
"Byte code contract is not payable, but source code contract is.">>]}].
validate(Contract1, Contract2) ->
ByteCode = #{ fate_code := FCode } = compile(fate, Contract1),
FCode1 = aeb_fate_code:serialize(aeb_fate_code:strip_init_function(FCode)),
Source = aeso_test_utils:read_contract(Contract2),
aeso_compiler:validate_byte_code(
ByteCode#{ byte_code := FCode1 }, Source,
case lists:member(Contract2, debug_mode_contracts()) of
true -> [debug_mode];
false -> []
end ++
[{backend, fate}, {include, {file_system, [aeso_test_utils:contract_path()]}}]).
case compile(fate, Contract1) of
ByteCode = #{ fate_code := FCode } ->
FCode1 = aeb_fate_code:serialize(aeb_fate_code:strip_init_function(FCode)),
Source = aeso_test_utils:read_contract(Contract2),
aeso_compiler:validate_byte_code(
ByteCode#{ byte_code := FCode1 }, Source,
case lists:member(Contract2, debug_mode_contracts()) of
true -> [debug_mode];
false -> []
end ++
[{backend, fate}, {include, {file_system, [aeso_test_utils:contract_path()]}}]);
Error -> print_and_throw(Error)
end.
print_and_throw(Err) ->
case Err of
ErrBin when is_binary(ErrBin) ->
io:format("\n~s", [ErrBin]),
error(ErrBin);
Errors ->
io:format("Compilation error:\n~s", [string:join([aeso_errors:pp(E) || E <- Errors], "\n\n")]),
error(compilation_error)
end.
+2 -2
View File
@@ -12,10 +12,10 @@ simple_contracts_test_() ->
fun(_) -> ok end,
[{"Parse a contract with an identity function.",
fun() ->
Text = "contract Identity =\n"
Text = "main contract Identity =\n"
" function id(x) = x\n",
?assertMatch(
[{contract, _, {con, _, "Identity"},
[{contract_main, _, {con, _, "Identity"},
[{letfun, _, {id, _, "id"}, [{id, _, "x"}], {id, _, "_"},
{id, _, "x"}}]}], parse_string(Text)),
ok
+1 -1
View File
@@ -1,5 +1,5 @@
contract Identity =
function main (x:int) = x
function main_fun (x:int) = x
function __call() = 12
+2 -2
View File
@@ -1,5 +1,5 @@
contract Remote =
entrypoint main : (int) => unit
contract interface Remote =
entrypoint main_fun : (int) => unit
contract AddrChain =
type o_type = oracle(string, map(string, int))
+1 -1
View File
@@ -1,5 +1,5 @@
contract Remote =
contract interface Remote =
entrypoint foo : () => unit
contract AddressLiterals =
+5
View File
@@ -0,0 +1,5 @@
contract C =
entrypoint f() = 123
contract D =
entrypoint f() = 123
+1 -1
View File
@@ -1,5 +1,5 @@
contract Remote =
contract interface Remote =
entrypoint foo : () => unit
contract AddressLiterals =
+1 -1
View File
@@ -1,4 +1,4 @@
contract Remote =
contract interface Remote =
entrypoint id : int => int
contract ProtectedCall =
+1 -1
View File
@@ -1,3 +1,3 @@
function square(x) = x ^ 2
contract Main =
entrypoint main() = square(10)
entrypoint main_fun() = square(10)
+28
View File
@@ -0,0 +1,28 @@
contract interface HigherOrderState =
entrypoint init : () => void
entrypoint apply : int => int
stateful entrypoint inc : int => unit
contract interface LowerDisorderAnarchy =
entrypoint init : (int) => void
main contract C =
// both `s` and `l` should be of type `HigherOrderState` in this test
stateful entrypoint run_clone(s : HigherOrderState, l : LowerDisorderAnarchy) : HigherOrderState =
let s1 = Chain.clone(ref=s)
let Some(s2) = Chain.clone(ref=s, protected=true)
let None = Chain.clone(ref=s, protected=true, gas=1)
let None = Chain.clone(ref=l, protected=true, 123) // since it should be HigherOrderState underneath
let s3 = Chain.clone(ref=s1)
require(s1.apply(2137) == 2137, "APPLY_S1_0")
require(s2.apply(2137) == 2137, "APPLY_S2_0")
require(s3.apply(2137) == 2137, "APPLY_S3_0")
s1.inc(1)
s2.inc(1)
s1.inc(1)
require(s1.apply(2137) == 2139, "APPLY_S1_2")
require(s2.apply(2137) == 2138, "APPLY_S2_1")
require(s3.apply(2137) == 2137, "APPLY_S3_0")
s1
+7
View File
@@ -0,0 +1,7 @@
contract interface I =
entrypoint init : () => void
contract C =
stateful entrypoint f(i : I) =
let Some(c1) = Chain.clone(ref=i, protected = true)
2
@@ -5,5 +5,5 @@ contract BadAENSresolve =
function fail() : t(int) =
AENS.resolve("foo.aet", "whatever")
entrypoint main() = ()
entrypoint main_fun() = ()
@@ -0,0 +1,5 @@
contract C =
entrypoint f : () => unit
main contract M =
entrypoint f() = 123
@@ -3,4 +3,4 @@ contract MapAsMapKey =
function foo(m) : t(int => int) = {[m] = 0}
entrypoint main() = ()
entrypoint main_fun() = ()
@@ -2,4 +2,4 @@ contract HigherOrderQueryType =
stateful function foo(o) : oracle_query(_, string ) =
Oracle.query(o, (x) => x + 1, 100, RelativeTTL(100), RelativeTTL(100))
entrypoint main() = ()
entrypoint main_fun() = ()
@@ -2,4 +2,4 @@ contract HigherOrderResponseType =
stateful function foo(o, q : oracle_query(string, _)) =
Oracle.respond(o, q, (x) => x + 1)
entrypoint main() = ()
entrypoint main_fun() = ()
@@ -1,2 +0,0 @@
namespace LastDeclarationIsNotAContract =
function add(x, y) = x + y
@@ -1,3 +1,3 @@
contract MissingDefinition =
entrypoint foo : int => int
entrypoint main() = foo(0)
entrypoint main_fun() = foo(0)
@@ -3,5 +3,5 @@ contract PolymorphicAENSresolve =
function fail() : option('a) =
AENS.resolve("foo.aet", "whatever")
entrypoint main() = ()
entrypoint main_fun() = ()
@@ -3,4 +3,4 @@ contract MapAsMapKey =
function foo(m) : t('a) = {[m] = 0}
entrypoint main() = ()
entrypoint main_fun() = ()
@@ -2,4 +2,4 @@ contract PolymorphicQueryType =
stateful function is_oracle(o) =
Oracle.check(o)
entrypoint main() = ()
entrypoint main_fun() = ()
@@ -2,4 +2,4 @@ contract PolymorphicResponseType =
function is_oracle(o : oracle(string, 'r)) =
Oracle.check(o)
entrypoint main(o : oracle(string, int)) = is_oracle(o)
entrypoint main_fun(o : oracle(string, int)) = is_oracle(o)
@@ -1,4 +1,4 @@
contract Remote =
contract interface Remote =
entrypoint foo : int => int
contract UnappliedContractCall =
@@ -1,5 +1,5 @@
contract UnappliedNamedArgBuiltin =
// Allowed in FATE, but not AEVM
stateful entrypoint main(s) =
stateful entrypoint main_fun(s) =
let reg = Oracle.register
reg(signature = s, Contract.address, 100, RelativeTTL(100)) : oracle(int, int)
+1 -1
View File
@@ -1,5 +1,5 @@
contract Remote =
contract interface Remote =
entrypoint up_to : (int) => list(int)
entrypoint sum : (list(int)) => int
entrypoint some_string : () => string
+1 -1
View File
@@ -1,4 +1,4 @@
contract Foo =
contract interface Foo =
entrypoint foo : () => int
contract Fail =
+28
View File
@@ -0,0 +1,28 @@
contract IntegerAdder =
entrypoint init() = ()
entrypoint addIntegers(x, y) = x + y
contract IntegerAdderHolder =
type state = IntegerAdder
stateful entrypoint init() = Chain.create() : IntegerAdder
entrypoint get() = state
contract IntegerAdderFactory =
entrypoint init() = ()
stateful entrypoint new() =
let i = Chain.create() : IntegerAdderHolder
i.get()
payable contract ValueAdder =
entrypoint init() = ()
stateful entrypoint addValue(x) =
let integerAdderFactory = Chain.create()
let adder = integerAdderFactory.new()
adder.addIntegers(x, Contract.balance)
main contract EnterpriseContract =
entrypoint init() = ()
stateful payable entrypoint increaseByThree(x) =
require(Call.value >= 3, "Price for addition = 3AEtto, insufficient funds")
let threeAdder = Chain.create(value = 3)
threeAdder.addValue(x)
+1 -1
View File
@@ -1,6 +1,6 @@
// Testing primitives for accessing the block chain environment
contract Interface =
contract interface Interface =
entrypoint contract_address : () => address
entrypoint call_origin : () => address
entrypoint call_caller : () => address
+1 -1
View File
@@ -1,4 +1,4 @@
contract Remote =
contract interface Remote =
entrypoint dummy : () => unit
contract Events =
+1 -1
View File
@@ -1,6 +1,6 @@
// An implementation of the factorial function where each recursive
// call is to another contract. Not the cheapest way to compute factorial.
contract FactorialServer =
contract interface FactorialServer =
entrypoint fac : (int) => int
contract Factorial =
+24
View File
@@ -0,0 +1,24 @@
contract interface Kaboom =
entrypoint init : () => void
contract Bakoom =
type state = int
entrypoint init(x, b) = if(b) x else 0
main contract Test =
stateful entrypoint test(k : Kaboom) =
let k_bad1 = Chain.clone() : Kaboom
let k_bad2 = Chain.clone(ref=k, 123, true)
let k_bad3 = Chain.clone(ref=k, gas=true)
let k_bad4 = Chain.create() : Kaboom
let k_gud1 = Chain.clone(ref=k)
let Some(k_gud2) = Chain.clone(ref=k, protected=true)
let Some(k_gud3) = Chain.clone(ref=k, value=10, protected=true, gas=123)
let b_bad1 = Chain.create() : Bakoom
let b_bad2 = Chain.create(123, true, protected=true) : Bakoom
let b_bad3 = Chain.create(123, true, value=true) : Bakoom
let b_gud1 = Chain.create(123, true) : Bakoom
let b_gud2 = Chain.create(123, true, value=100) : Bakoom
b_gud1
+2 -3
View File
@@ -1,3 +1,2 @@
contract Identity =
entrypoint main (x:int) = x
main contract Identity =
entrypoint main_fun (x:int) = x
+5
View File
@@ -0,0 +1,5 @@
contract interface ContractOne =
entrypoint foo() = "foo"
contract ContractTwo =
entrypoint bar() = "bar"
+1 -1
View File
@@ -16,7 +16,7 @@ contract LHSMatching =
let null(_ :: _) = false
!null(xs)
entrypoint main() =
entrypoint main_fun() =
from_some(Some([0]))
++ append([length([true]), 2, 3], [4, 5, 6])
++ [7 | if (local_match([false]))]
+1 -1
View File
@@ -1,3 +1,3 @@
contract MissingEventType =
entrypoint main() =
entrypoint main_fun() =
Chain.event("MAIN")
+6 -4
View File
@@ -1,5 +1,7 @@
contract ContractOne =
entrypoint foo() = "foo"
contract Child =
entrypoint
add2 : int => int
add2(x) = x + 2
contract ContractTwo =
entrypoint bar() = "bar"
main contract Main =
entrypoint add4(x, c : Child) = c.add2(x) + 2
@@ -0,0 +1,5 @@
main contract C =
entrypoint f() = 123
main contract D =
entrypoint f() = 123
+2
View File
@@ -0,0 +1,2 @@
contract interface C =
entrypoint f : () => unit
+1 -1
View File
@@ -1,4 +1,4 @@
contract C1 =
contract interface C1 =
entrypoint f : int
contract C =
+1 -1
View File
@@ -1,4 +1,4 @@
contract Remote =
contract interface Remote =
entrypoint id : int => int
contract ProtectedCall =
+5 -5
View File
@@ -1,18 +1,18 @@
contract Remote1 =
entrypoint main : (int) => int
contract interface Remote1 =
entrypoint main_fun : (int) => int
contract Remote2 =
contract interface Remote2 =
entrypoint call : (Remote1, int) => int
contract Remote3 =
contract interface Remote3 =
entrypoint get : () => int
entrypoint tick : () => unit
contract RemoteCall =
stateful entrypoint call(r : Remote1, x : int) : int =
r.main(gas = 10000, value = 10, x)
r.main_fun(gas = 10000, value = 10, x)
entrypoint staged_call(r1 : Remote1, r2 : Remote2, x : int) =
r2.call(r1, x)
+1 -1
View File
@@ -1,5 +1,5 @@
contract SpendContract =
contract interface SpendContract =
entrypoint withdraw : (int) => int
contract SpendTest =
+1 -1
View File
@@ -1,5 +1,5 @@
include "String.aes"
contract Remote =
contract interface Remote =
record rstate = { i : int, s : string, m : map(int, int) }
entrypoint look_at : (rstate) => unit
+1 -1
View File
@@ -1,5 +1,5 @@
contract Remote =
contract interface Remote =
stateful entrypoint remote_spend : (address, int) => unit
entrypoint remote_pure : int => int
+9 -99
View File
@@ -1,102 +1,12 @@
// This is a custom test file if you need to run a compiler without
// changing aeso_compiler_tests.erl
contract Identity =
// type xy = {x:int, y:int}
// type xz = {x:int, z:int}
// type yz = {y:int, z:int}
record point = {x:int,y:int}
record cp('a) = {color: string, p:'a}
//type intpoint = point(int)
// //if (x==42) 1 else (x*x)
// }
//let baz() = {age:3, name:(4:int)}
//let foo(a,b,c) = c
// let rec fac(n) = if((n:int)==0) 1 else (n*fac(n-1))
// and main(x) = x::[x+1]
// let lentr(l) = lent(0,l)
// let rec len(l) =
// switch(l) {
// | [] => 0
// | x::xs => 1+len(xs)
// }
// let lent(n,l) =
// switch (l) {
// | [] => n
// | (x::xs) => lent(n+1,xs)
// }
// let rec app(a,b) =
// switch(a) {
// | [] => b
// | (x::xs) => x::app(xs,b)
// }
// let rec revt(l,r) =
// switch(l) {
// | [] => r
// | x::xs => revt(xs,x::r)
// }
// let rev(l) = revt(l,[])
// let main(x:int) = {
// switch(rev([1,2,3])) {
// | h::_ => h
// }
// }
//let fac(n:int) = {
// if (n==0) 1 else (n*fac(n-1))
//}
//let main(x) = switch((12,34)) {
//| (13,_) => x
//| (_,a) => x+a
// | y => y+1
// }
//let main(x) = ({y:0>1, x:x==0}:point(bool))
//let main(x) = x
//let main(x) = len(1::2::[])
//let main(x) = ((x,x):list('a))
// let main(x) = switch("a") {
// | "b" => 0
// | "a" => 1
// | "c" => 2
// }
//let main(x) = x.color+1
//let main(x) = switch(({x:x, y:x+1}:cp(int))) {
// | {y:xx} => xx
// }
//let main(x) = {x:0, y:1, z:2}
// let id(x) = x
// let double(x) = x+x
// let pair(x) = (1,2)
// let unit(x) = ()
// let tuples(x) = ((1,x),(2,3,4))
// let singleton(x) = [x]
// let rec seq(n) = if (n==0) [] else (app(seq(n-1),[n]))
// let idString(s:string) = s
// let pairString(s:string) = (s,s)
// let revStrings(ss:list(string))=rev(ss)
// let makePoint(x,y) = {x:x, y:y}
// let getx(x) = x.x
// let updatex(p,x) = p{x:x}
// let quad(x) = {let y=x+x; let z=y+y; z;}
// let noblock(x) = {x; x}
// let unit(x) = ()
// let foo(x) = switch (x) {
// | y => y+1
// }
// let p(x) = {color:"blue", p:{x:x, y:x+1}}
//let twice(f,x) = f(f(x))
// let twice(f,x) = f(f(x))
// let double(x) = x+x
// let main(x) = twice((y=>y+y),x)
// let rec map(f,xs) = switch(xs) {
// | [] => []
// | (x::ys) => f(x)::map(f,ys)
// }
// let id(x) = x
// let main(xs) = map(double,xs)
function z(f,x) = x
function s(n) = (f,x)=>f(n(f,x))
function add(m,n) = (f,x)=>m(f,n(f,x))
include "List.aes"
entrypoint main() =
let three=s(s(s(z)))
add(three,three)
(((i)=>i+1),0)
contract IntegerHolder =
type state = int
entrypoint init(x) = x
entrypoint get() = state
main contract Test =
stateful entrypoint f(c) = Chain.clone(ref=c, 123)
+1 -1
View File
@@ -1,5 +1,5 @@
contract Remote =
contract interface Remote =
type themap = map(int, string)
entrypoint foo : () => themap
+1 -1
View File
@@ -9,7 +9,7 @@
// Oracle.extend
include "String.aes"
contract UnappliedBuiltins =
entrypoint main() = ()
entrypoint main_fun() = ()
type o = oracle(int, int)
type t = list(int * string)
type m = map(int, int)