templates.test_errors_metadata

  1import smartpy as sp
  2
  3
  4@sp.module
  5def main():
  6    @sp.effects()
  7    def l(x):
  8        if x:
  9            raise "A"
 10        else:
 11            raise ()
 12
 13    init_type: type = sp.record(
 14        l=sp.lambda_(sp.bool, sp.unit), l2=sp.lambda_(sp.bool, sp.unit)
 15    )
 16
 17    class C(sp.Contract):
 18        def __init__(self, l2):
 19            self.data.l = l
 20            self.data.l2 = l2
 21
 22        @sp.entrypoint
 23        def ep1(self):
 24            raise "A"
 25
 26        @sp.entrypoint
 27        def ep2(self):
 28            raise "B"
 29
 30        @sp.entrypoint
 31        def ep3(self):
 32            raise "A"
 33
 34        @sp.entrypoint
 35        def ep4(self):
 36            raise sp.nat(42)
 37
 38        @sp.entrypoint
 39        def ep5(self):
 40            raise ("A", 5)
 41
 42        @sp.entrypoint
 43        def exec_l(self):
 44            self.data.l(True)
 45
 46        @sp.entrypoint
 47        def exec_l2(self):
 48            self.data.l2(True)
 49
 50        @sp.onchain_view
 51        def v1(self, x):
 52            if x:
 53                raise "A"
 54            else:
 55                return ()
 56
 57        @sp.onchain_view
 58        def v2(self, x):
 59            if x:
 60                raise "C"
 61            else:
 62                return ()
 63
 64    class Factory(sp.Contract):
 65        def __init__(self):
 66            self.data.created = None
 67
 68        @sp.entrypoint
 69        def create(self, l2):
 70            self.data.created = sp.Some(
 71                sp.create_contract(C, None, sp.mutez(0), sp.record(l=l, l2=l2))
 72            )
 73
 74        @sp.entrypoint
 75        def ep1(self):
 76            created = self.data.created.unwrap_some()
 77            contract = sp.contract(sp.unit, created, entrypoint="ep1")
 78            sp.transfer((), sp.tez(0), contract.unwrap_some())
 79
 80        @sp.entrypoint
 81        def ep2(self):
 82            created = self.data.created.unwrap_some()
 83            contract = sp.contract(sp.unit, created, entrypoint="ep2")
 84            sp.transfer((), sp.tez(0), contract.unwrap_some())
 85
 86        @sp.entrypoint
 87        def ep3(self):
 88            created = self.data.created.unwrap_some()
 89            contract = sp.contract(sp.unit, created, entrypoint="ep3")
 90            sp.transfer((), sp.tez(0), contract.unwrap_some())
 91
 92        @sp.entrypoint
 93        def exec_l(self):
 94            created = self.data.created.unwrap_some()
 95            contract = sp.contract(sp.unit, created, entrypoint="exec_l")
 96            sp.transfer((), sp.tez(0), contract.unwrap_some())
 97
 98        @sp.entrypoint
 99        def exec_l2(self):
100            created = self.data.created.unwrap_some()
101            contract = sp.contract(sp.unit, created, entrypoint="exec_l2")
102            sp.transfer((), sp.tez(0), contract.unwrap_some())
103
104        @sp.entrypoint
105        def ep_v1(self):
106            created = self.data.created.unwrap_some()
107            _ = sp.view("v1", created, True, sp.unit)
108
109        @sp.entrypoint
110        def ep_v2(self):
111            created = self.data.created.unwrap_some()
112            _ = sp.view("v2", created, True, sp.unit)
113
114
115def run_test(f, value, specified):
116    failed = False
117    try:
118        f()
119    except Exception as e:
120        assert e.value == value
121        assert e.specified == specified
122        failed = True
123    assert failed
124
125
126@sp.add_test()
127def test():
128    s = sp.test_scenario("Error replacement", main)
129
130    # Error aren't mapped without flag
131    c1 = main.C(main.l)
132    s += c1
133    run_test(c1.ep1, "A", None)
134    run_test(c1.ep2, "B", None)
135    run_test(c1.ep3, "A", None)
136    run_test(c1.exec_l, "A", None)
137    run_test(c1.exec_l2, "A", None)
138    run_test(lambda: s.compute(c1.v1(True)), "A", None)
139    run_test(lambda: s.compute(c1.v2(True)), "C", None)
140
141    # Mapped errors
142    s.add_flag("exceptions", "metadata-id")
143    c2 = main.C(main.l)
144    s += c2
145    run_test(c2.ep1, "0", "A")
146    run_test(c2.ep2, "1", "B")
147    run_test(c2.ep3, "0", "A")
148    run_test(c1.exec_l, "A", None)
149    run_test(c1.exec_l2, "A", None)
150    run_test(lambda: s.compute(c2.v1(True)), "0", "A")
151    run_test(lambda: s.compute(c2.v2(True)), "2", "C")
152
153    metadata = sp.create_tzip16_metadata(error_map=c2.instantiation_result["error_map"])
154    assert (
155        metadata["errors"].__str__()
156        == "[{'error': {'int': '2'}, 'expansion': {'string': 'C'}}, {'error': {'int': '1'}, 'expansion': {'string': 'B'}}, {'error': {'int': '0'}, 'expansion': {'string': 'A'}}]"
157    )
158
159    # Flag doesn't affect already instantiated contracts
160    run_test(c1.ep1, "A", None)
161    run_test(c1.ep2, "B", None)
162    run_test(lambda: s.compute(c1.v1(True)), "A", None)
163    run_test(lambda: s.compute(c1.v2(True)), "C", None)
164
165    # Dynamically created contracts
166    f1 = main.Factory()
167    s += f1
168
169    f1.create(main.l)
170    run_test(f1.ep1, "0", "A")
171    run_test(f1.ep2, "1", "B")
172    run_test(f1.ep3, "0", "A")
173    run_test(f1.exec_l, "A", None)
174    run_test(f1.exec_l2, "A", None)
175    run_test(f1.ep_v1, "0", "A")
176    run_test(f1.ep_v2, "2", "C")
def run_test(f, value, specified):
116def run_test(f, value, specified):
117    failed = False
118    try:
119        f()
120    except Exception as e:
121        assert e.value == value
122        assert e.specified == specified
123        failed = True
124    assert failed