Exemple #1
0
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
Exemple #2
0
 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(),
             )),
     )
Exemple #3
0
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
Exemple #4
0
 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()),
                 )),
     )
Exemple #5
0
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
Exemple #6
0
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()
Exemple #7
0
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)
Exemple #8
0
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)