1# Collatz, calling other contracts - Example for illustrative purposes only.
2
3import smartpy as sp
4
5# Compute the length of the nth Collatz sequence
6# (https://oeis.org/A006577) with on-chain continuations
7
8
9@sp.module
10def main():
11 class OnEven(sp.Contract):
12 @sp.entrypoint
13 def run(self, params):
14 sp.transfer(params.x / 2, sp.mutez(0), params.k)
15
16 class OnOdd(sp.Contract):
17 @sp.entrypoint
18 def run(self, params):
19 sp.transfer(3 * params.x + 1, sp.mutez(0), params.k)
20
21 class Collatz(sp.Contract):
22 def __init__(self, onEven, onOdd):
23 self.data.onEven = onEven
24 self.data.onOdd = onOdd
25 self.data.counter = 0
26
27 @sp.entrypoint
28 def run(self, x):
29 if x > 1:
30 self.data.counter += 1
31
32 params = sp.record(k=sp.self_entrypoint("run"), x=x)
33 if sp.mod(x, 2) == 0:
34 sp.transfer(
35 params,
36 sp.mutez(0),
37 sp.contract(
38 sp.record(k=sp.contract[sp.int_or_nat], x=sp.int_or_nat),
39 self.data.onEven,
40 ).unwrap_some(),
41 )
42 else:
43 sp.transfer(
44 params,
45 sp.mutez(0),
46 sp.contract(
47 sp.record(k=sp.contract[sp.int_or_nat], x=sp.int_or_nat),
48 self.data.onOdd,
49 ).unwrap_some(),
50 )
51
52 @sp.entrypoint
53 def reset(self):
54 self.data.counter = 0
55
56
57@sp.add_test()
58def test():
59 scenario = sp.test_scenario("Collatz", main)
60 scenario.h1("Collatz template - Inter-Contract Calls")
61 on_even = main.OnEven()
62 scenario += on_even
63 on_odd = main.OnOdd()
64 scenario += on_odd
65 collatz = main.Collatz(onEven=on_even.address, onOdd=on_odd.address)
66 scenario += collatz
67 # See https://oeis.org/A006577/list
68 collatz.run(42)
69 scenario.verify(collatz.data.counter == 8)
70 collatz.reset()
71 collatz.run(5)
72 scenario.verify(collatz.data.counter == 5)