templates.collatz

 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)