def test_StaticArray_set_values(): value = abi.StaticArray(abi.StaticArrayTypeSpec(abi.Uint64TypeSpec(), 10)) with pytest.raises(pt.TealInputError): value.set([]) with pytest.raises(pt.TealInputError): value.set([abi.Uint64()] * 9) with pytest.raises(pt.TealInputError): value.set([abi.Uint64()] * 11) with pytest.raises(pt.TealInputError): value.set([abi.Uint16()] * 10) with pytest.raises(pt.TealInputError): value.set([abi.Uint64()] * 9 + [abi.Uint16()]) values = [abi.Uint64() for _ in range(10)] expr = value.set(values) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expectedExpr = value.stored_value.store(_encode_tuple(values)) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected
def named_tuple_field_access( a_0: abi.Bool, a_1: abi.Address, a_2: abi.Tuple2[abi.Uint64, abi.Bool], a_3: abi.StaticArray[abi.Byte, L[10]], a_4: abi.StaticArray[abi.Bool, L[4]], a_5: abi.Uint64, ): return Seq( (v_tuple := NamedTupleExample()).set(a_0, a_1, a_2, a_3, a_4, a_5), (v_a := abi.Bool()).set(v_tuple.a), (v_b := abi.Address()).set(v_tuple.b), (v_c := abi.make(abi.Tuple2[abi.Uint64, abi.Bool])).set(v_tuple.c), (v_d := abi.make(abi.StaticArray[abi.Byte, L[10]])).set(v_tuple.d), (v_e := abi.make(abi.StaticArray[abi.Bool, L[4]])).set(v_tuple.e), (v_f := abi.Uint64()).set(v_tuple.f), Return( And( a_0.get() == v_a.get(), a_1.get() == v_b.get(), a_2.encode() == v_c.encode(), a_3.encode() == v_d.encode(), a_4.encode() == v_e.encode(), a_5.get() == v_f.get(), )), )
def test_StaticArray_set_copy(): value = abi.StaticArray(abi.StaticArrayTypeSpec(abi.Uint64TypeSpec(), 10)) otherArray = abi.StaticArray( abi.StaticArrayTypeSpec(abi.Uint64TypeSpec(), 10)) with pytest.raises(pt.TealInputError): value.set( abi.StaticArray(abi.StaticArrayTypeSpec(abi.Uint64TypeSpec(), 11))) with pytest.raises(pt.TealInputError): value.set( abi.StaticArray(abi.StaticArrayTypeSpec(abi.Uint8TypeSpec(), 10))) with pytest.raises(pt.TealInputError): value.set(abi.Uint64()) expr = value.set(otherArray) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expected = pt.TealSimpleBlock([ pt.TealOp(None, pt.Op.load, otherArray.stored_value.slot), pt.TealOp(None, pt.Op.store, value.stored_value.slot), ]) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected
def abi_sum(to_sum: abi.DynamicArray[abi.Uint64], *, output: abi.Uint64) -> Expr: i = ScratchVar(TealType.uint64) value_at_index = abi.Uint64() return Seq( output.set(0), For(i.store(Int(0)), i.load() < to_sum.length(), i.store(i.load() + Int(1))).Do( Seq( to_sum[i.load()].store_into(value_at_index), output.set(output.get() + value_at_index.get()), )), )
def user_guide_snippet_ABIReturnSubroutine(): from pyteal import ( ABIReturnSubroutine, Expr, For, Int, ScratchVar, Seq, Txn, TealType, ) from pyteal import abi # --- BEGIN doc-comment --- # @ABIReturnSubroutine def abi_sum(to_sum: abi.DynamicArray[abi.Uint64], *, output: abi.Uint64) -> Expr: i = ScratchVar(TealType.uint64) value_at_index = abi.Uint64() return Seq( output.set(0), For(i.store(Int(0)), i.load() < to_sum.length(), i.store(i.load() + Int(1))).Do( Seq( to_sum[i.load()].store_into(value_at_index), output.set(output.get() + value_at_index.get()), )), ) program = Seq( (to_sum_arr := abi.make(abi.DynamicArray[abi.Uint64])).decode( Txn.application_args[1]), (res := abi.Uint64()).set(abi_sum(to_sum_arr)), pt.abi.MethodReturn(res), Int(1), ) # --- END doc-comment --- # return program
def test_NamedTuple_getitem(test_case: type[abi.NamedTuple]): tuple_value = test_case() tuple_len_static = tuple_value.type_spec().length_static() for i in range(tuple_len_static): elem_by_field: abi.TupleElement = getattr(tuple_value, f"f{i}") elem_by_index: abi.TupleElement = tuple_value[i] assert ( type(elem_by_field) is abi.TupleElement ), f"Test case {test_case} at field f{i} must be TupleElement" assert ( type(elem_by_index) is abi.TupleElement ), f"Test case {test_case} at index {i} must be TupleElement" assert ( elem_by_field.index == i ), f"Test case {test_case} at field f{i} should have index {i}." assert ( elem_by_index.index == i ), f"Test case {test_case} at index {i} should have index {i}." assert ( elem_by_field.tuple is tuple_value ), f"Test case {test_case} at field f{i} should have attr tuple == {test_case}." assert ( elem_by_index.tuple is tuple_value ), f"Test case {test_case} at index {i} should have attr tuple == {test_case}." assert ( elem_by_field.produced_type_spec() == elem_by_index.produced_type_spec() ), f"Test case {test_case} at field f{i} type spec unmatching: {elem_by_field.produced_type_spec()} != {elem_by_index.produced_type_spec()}." with pytest.raises(KeyError): tuple_value.aaaaa with pytest.raises(pt.TealInputError): tuple_value.f0 = abi.Uint64()
def test_indexTuple(): class IndexTest(NamedTuple): types: List[abi.TypeSpec] typeIndex: int expected: Callable[[abi.BaseType], pt.Expr] # variables used to construct the tests uint64_t = abi.Uint64TypeSpec() byte_t = abi.ByteTypeSpec() bool_t = abi.BoolTypeSpec() tuple_t = abi.TupleTypeSpec(abi.BoolTypeSpec(), abi.BoolTypeSpec()) dynamic_array_t1 = abi.DynamicArrayTypeSpec(abi.Uint64TypeSpec()) dynamic_array_t2 = abi.DynamicArrayTypeSpec(abi.Uint16TypeSpec()) encoded = pt.Bytes("encoded") tests: List[IndexTest] = [ IndexTest( types=[uint64_t], typeIndex=0, expected=lambda output: output.decode(encoded), ), IndexTest( types=[uint64_t, uint64_t], typeIndex=0, expected=lambda output: output.decode(encoded, length=pt.Int(8)), ), IndexTest( types=[uint64_t, uint64_t], typeIndex=1, expected=lambda output: output.decode(encoded, start_index=pt.Int(8)), ), IndexTest( types=[uint64_t, byte_t, uint64_t], typeIndex=1, expected=lambda output: output.decode( encoded, start_index=pt.Int(8), length=pt.Int(1) ), ), IndexTest( types=[uint64_t, byte_t, uint64_t], typeIndex=2, expected=lambda output: output.decode( encoded, start_index=pt.Int(9), length=pt.Int(8) ), ), IndexTest( types=[bool_t], typeIndex=0, expected=lambda output: output.decode_bit(encoded, pt.Int(0)), ), IndexTest( types=[bool_t, bool_t], typeIndex=0, expected=lambda output: output.decode_bit(encoded, pt.Int(0)), ), IndexTest( types=[bool_t, bool_t], typeIndex=1, expected=lambda output: output.decode_bit(encoded, pt.Int(1)), ), IndexTest( types=[uint64_t, bool_t], typeIndex=1, expected=lambda output: output.decode_bit(encoded, pt.Int(8 * 8)), ), IndexTest( types=[uint64_t, bool_t, bool_t], typeIndex=1, expected=lambda output: output.decode_bit(encoded, pt.Int(8 * 8)), ), IndexTest( types=[uint64_t, bool_t, bool_t], typeIndex=2, expected=lambda output: output.decode_bit(encoded, pt.Int(8 * 8 + 1)), ), IndexTest( types=[bool_t, uint64_t], typeIndex=0, expected=lambda output: output.decode_bit(encoded, pt.Int(0)), ), IndexTest( types=[bool_t, uint64_t], typeIndex=1, expected=lambda output: output.decode(encoded, start_index=pt.Int(1)), ), IndexTest( types=[bool_t, bool_t, uint64_t], typeIndex=0, expected=lambda output: output.decode_bit(encoded, pt.Int(0)), ), IndexTest( types=[bool_t, bool_t, uint64_t], typeIndex=1, expected=lambda output: output.decode_bit(encoded, pt.Int(1)), ), IndexTest( types=[bool_t, bool_t, uint64_t], typeIndex=2, expected=lambda output: output.decode(encoded, start_index=pt.Int(1)), ), IndexTest( types=[tuple_t], typeIndex=0, expected=lambda output: output.decode(encoded) ), IndexTest( types=[byte_t, tuple_t], typeIndex=1, expected=lambda output: output.decode(encoded, start_index=pt.Int(1)), ), IndexTest( types=[tuple_t, byte_t], typeIndex=0, expected=lambda output: output.decode( encoded, start_index=pt.Int(0), length=pt.Int(tuple_t.byte_length_static()), ), ), IndexTest( types=[byte_t, tuple_t, byte_t], typeIndex=1, expected=lambda output: output.decode( encoded, start_index=pt.Int(1), length=pt.Int(tuple_t.byte_length_static()), ), ), IndexTest( types=[dynamic_array_t1], typeIndex=0, expected=lambda output: output.decode( encoded, start_index=pt.ExtractUint16(encoded, pt.Int(0)) ), ), IndexTest( types=[byte_t, dynamic_array_t1], typeIndex=1, expected=lambda output: output.decode( encoded, start_index=pt.ExtractUint16(encoded, pt.Int(1)) ), ), IndexTest( types=[dynamic_array_t1, byte_t], typeIndex=0, expected=lambda output: output.decode( encoded, start_index=pt.ExtractUint16(encoded, pt.Int(0)) ), ), IndexTest( types=[byte_t, dynamic_array_t1, byte_t], typeIndex=1, expected=lambda output: output.decode( encoded, start_index=pt.ExtractUint16(encoded, pt.Int(1)) ), ), IndexTest( types=[byte_t, dynamic_array_t1, byte_t, dynamic_array_t2], typeIndex=1, expected=lambda output: output.decode( encoded, start_index=pt.ExtractUint16(encoded, pt.Int(1)), end_index=pt.ExtractUint16(encoded, pt.Int(4)), ), ), IndexTest( types=[byte_t, dynamic_array_t1, byte_t, dynamic_array_t2], typeIndex=3, expected=lambda output: output.decode( encoded, start_index=pt.ExtractUint16(encoded, pt.Int(4)) ), ), IndexTest( types=[byte_t, dynamic_array_t1, tuple_t, dynamic_array_t2], typeIndex=1, expected=lambda output: output.decode( encoded, start_index=pt.ExtractUint16(encoded, pt.Int(1)), end_index=pt.ExtractUint16(encoded, pt.Int(4)), ), ), IndexTest( types=[byte_t, dynamic_array_t1, tuple_t, dynamic_array_t2], typeIndex=3, expected=lambda output: output.decode( encoded, start_index=pt.ExtractUint16(encoded, pt.Int(4)) ), ), IndexTest( types=[byte_t, dynamic_array_t2, bool_t, bool_t, dynamic_array_t2], typeIndex=1, expected=lambda output: output.decode( encoded, start_index=pt.ExtractUint16(encoded, pt.Int(1)), end_index=pt.ExtractUint16(encoded, pt.Int(4)), ), ), IndexTest( types=[byte_t, dynamic_array_t1, bool_t, bool_t, dynamic_array_t2], typeIndex=4, expected=lambda output: output.decode( encoded, start_index=pt.ExtractUint16(encoded, pt.Int(4)) ), ), ] for i, test in enumerate(tests): output = test.types[test.typeIndex].new_instance() expr = _index_tuple(test.types, encoded, test.typeIndex, output) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expected, _ = test.expected(output).__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected, "Test at index {} failed".format(i) with pytest.raises(ValueError): _index_tuple(test.types, encoded, len(test.types), output) with pytest.raises(ValueError): _index_tuple(test.types, encoded, -1, output) otherType = abi.Uint64() if output.type_spec() == otherType.type_spec(): otherType = abi.Uint16() with pytest.raises(TypeError): _index_tuple(test.types, encoded, test.typeIndex, otherType)
def test_encodeTuple(): class EncodeTest(NamedTuple): types: List[abi.BaseType] expected: pt.Expr # variables used to construct the tests uint64_a = abi.Uint64() uint64_b = abi.Uint64() uint16_a = abi.Uint16() uint16_b = abi.Uint16() bool_a = abi.Bool() bool_b = abi.Bool() tuple_a = abi.Tuple(abi.TupleTypeSpec(abi.BoolTypeSpec(), abi.BoolTypeSpec())) dynamic_array_a = abi.DynamicArray(abi.DynamicArrayTypeSpec(abi.Uint64TypeSpec())) dynamic_array_b = abi.DynamicArray(abi.DynamicArrayTypeSpec(abi.Uint16TypeSpec())) dynamic_array_c = abi.DynamicArray(abi.DynamicArrayTypeSpec(abi.BoolTypeSpec())) tail_holder = pt.ScratchVar() encoded_tail = pt.ScratchVar() tests: List[EncodeTest] = [ EncodeTest(types=[], expected=pt.Bytes("")), EncodeTest(types=[uint64_a], expected=uint64_a.encode()), EncodeTest( types=[uint64_a, uint64_b], expected=pt.Concat(uint64_a.encode(), uint64_b.encode()), ), EncodeTest(types=[bool_a], expected=bool_a.encode()), EncodeTest( types=[bool_a, bool_b], expected=_encode_bool_sequence([bool_a, bool_b]) ), EncodeTest( types=[bool_a, bool_b, uint64_a], expected=pt.Concat( _encode_bool_sequence([bool_a, bool_b]), uint64_a.encode() ), ), EncodeTest( types=[uint64_a, bool_a, bool_b], expected=pt.Concat( uint64_a.encode(), _encode_bool_sequence([bool_a, bool_b]) ), ), EncodeTest( types=[uint64_a, bool_a, bool_b, uint64_b], expected=pt.Concat( uint64_a.encode(), _encode_bool_sequence([bool_a, bool_b]), uint64_b.encode(), ), ), EncodeTest( types=[uint64_a, bool_a, uint64_b, bool_b], expected=pt.Concat( uint64_a.encode(), bool_a.encode(), uint64_b.encode(), bool_b.encode() ), ), EncodeTest(types=[tuple_a], expected=tuple_a.encode()), EncodeTest( types=[uint64_a, tuple_a, bool_a, bool_b], expected=pt.Concat( uint64_a.encode(), tuple_a.encode(), _encode_bool_sequence([bool_a, bool_b]), ), ), EncodeTest( types=[dynamic_array_a], expected=pt.Concat( pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(2), uint16_a.encode(), ), tail_holder.load(), ), ), EncodeTest( types=[uint64_a, dynamic_array_a], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2), uint16_a.encode(), ), tail_holder.load(), ), ), EncodeTest( types=[uint64_a, dynamic_array_a, uint64_b], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2 + 8), uint16_a.encode(), ), uint64_b.encode(), tail_holder.load(), ), ), EncodeTest( types=[uint64_a, dynamic_array_a, bool_a, bool_b], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2 + 1), uint16_a.encode(), ), _encode_bool_sequence([bool_a, bool_b]), tail_holder.load(), ), ), EncodeTest( types=[uint64_a, dynamic_array_a, uint64_b, dynamic_array_b], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2 + 8 + 2), uint16_b.set(uint16_a.get() + pt.Len(encoded_tail.load())), uint16_a.encode(), ), uint64_b.encode(), pt.Seq( encoded_tail.store(dynamic_array_b.encode()), tail_holder.store( pt.Concat(tail_holder.load(), encoded_tail.load()) ), uint16_a.set(uint16_b), uint16_a.encode(), ), tail_holder.load(), ), ), EncodeTest( types=[ uint64_a, dynamic_array_a, uint64_b, dynamic_array_b, bool_a, bool_b, dynamic_array_c, ], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2 + 8 + 2 + 1 + 2), uint16_b.set(uint16_a.get() + pt.Len(encoded_tail.load())), uint16_a.encode(), ), uint64_b.encode(), pt.Seq( encoded_tail.store(dynamic_array_b.encode()), tail_holder.store( pt.Concat(tail_holder.load(), encoded_tail.load()) ), uint16_a.set(uint16_b), uint16_b.set(uint16_a.get() + pt.Len(encoded_tail.load())), uint16_a.encode(), ), _encode_bool_sequence([bool_a, bool_b]), pt.Seq( encoded_tail.store(dynamic_array_c.encode()), tail_holder.store( pt.Concat(tail_holder.load(), encoded_tail.load()) ), uint16_a.set(uint16_b), uint16_a.encode(), ), tail_holder.load(), ), ), ] for i, test in enumerate(tests): expr = _encode_tuple(test.types) assert expr.type_of() == pt.TealType.bytes assert not expr.has_return() expected, _ = test.expected.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) if any(t.type_spec().is_dynamic() for t in test.types): with pt.TealComponent.Context.ignoreExprEquality(): with pt.TealComponent.Context.ignoreScratchSlotEquality(): assert actual == expected, "Test at index {} failed".format(i) assert pt.TealBlock.MatchScratchSlotReferences( pt.TealBlock.GetReferencedScratchSlots(actual), pt.TealBlock.GetReferencedScratchSlots(expected), ) continue with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected, "Test at index {} failed".format(i)