Beispiel #1
0
def test_evaluate_subroutine_no_args():
    cases = (
        (pt.TealType.none, pt.Return()),
        (pt.TealType.uint64, pt.Int(1) + pt.Int(2)),
        (pt.TealType.uint64, pt.Return(pt.Int(1) + pt.Int(2))),
        (pt.TealType.bytes, pt.Bytes("value")),
        (pt.TealType.bytes, pt.Return(pt.Bytes("value"))),
    )

    for (returnType, returnValue) in cases:

        def mySubroutine():
            return returnValue

        definition = pt.SubroutineDefinition(mySubroutine, returnType)
        declaration = evaluate_subroutine(definition)

        assert isinstance(declaration, pt.SubroutineDeclaration)
        assert declaration.subroutine is definition

        assert declaration.type_of() == returnValue.type_of()
        assert declaration.has_return() == returnValue.has_return()

        options.setSubroutine(definition)
        expected, _ = pt.Seq([returnValue]).__teal__(options)

        actual, _ = declaration.__teal__(options)
        options.setSubroutine(None)
        assert actual == expected
Beispiel #2
0
def test_opup_explicit():
    mode = OpUpMode.Explicit
    with pytest.raises(pt.TealInputError) as err:
        opup = OpUp(mode)
    assert "target_app_id must be specified in Explicit OpUp mode" in str(
        err.value)

    with pytest.raises(pt.TealTypeError):
        opup = OpUp(mode, pt.Bytes("appid"))

    opup = OpUp(mode, pt.Int(1))

    with pytest.raises(pt.TealTypeError):
        opup.ensure_budget(pt.Bytes("budget"))

    with pytest.raises(pt.TealTypeError):
        opup.maximize_budget(pt.Bytes("fee"))

    assert opup.target_app_id == pt.Int(1)

    # verify correct usage doesn't cause an error
    _ = pt.Seq(opup.ensure_budget(pt.Int(500) + pt.Int(1000)),
               pt.Return(pt.Int(1)))

    _ = pt.Seq(opup.maximize_budget(pt.Txn.fee() - pt.Int(100)),
               pt.Return(pt.Int(1)))
Beispiel #3
0
def test_if_has_return():
    exprWithReturn = pt.If(pt.Int(1), pt.Return(pt.Int(1)), pt.Return(pt.Int(0)))
    assert exprWithReturn.has_return()

    exprWithoutReturn = pt.If(pt.Int(1), pt.Int(1), pt.Int(0))
    assert not exprWithoutReturn.has_return()

    exprSemiReturn = pt.If(
        pt.Int(1),
        pt.Return(pt.Int(1)),
        pt.App.globalPut(pt.Bytes("key"), pt.Bytes("value")),
    )
    assert not exprSemiReturn.has_return()
Beispiel #4
0
def test_cond_has_return():
    exprWithReturn = pt.Cond([pt.Int(1), pt.Return(pt.Int(1))],
                             [pt.Int(0), pt.Return(pt.Int(0))])
    assert exprWithReturn.has_return()

    exprWithoutReturn = pt.Cond([pt.Int(1), pt.Bytes("one")],
                                [pt.Int(0), pt.Bytes("zero")])
    assert not exprWithoutReturn.has_return()

    exprSemiReturn = pt.Cond(
        [pt.Int(1), pt.Return(pt.Int(1))],
        [pt.Int(0),
         pt.App.globalPut(pt.Bytes("key"), pt.Bytes("value"))],
    )
    assert not exprSemiReturn.has_return()
Beispiel #5
0
def test_opup_oncall():
    mode = OpUpMode.OnCall
    opup = OpUp(mode)

    with pytest.raises(pt.TealTypeError):
        opup.ensure_budget(pt.Bytes("budget"))

    with pytest.raises(pt.TealTypeError):
        opup.maximize_budget(pt.Bytes("fee"))

    # verify correct usage doesn't cause an error
    _ = pt.Seq(opup.ensure_budget(pt.Int(500) + pt.Int(1000)),
               pt.Return(pt.Int(1)))

    _ = pt.Seq(opup.maximize_budget(pt.Txn.fee() - pt.Int(100)),
               pt.Return(pt.Int(1)))
Beispiel #6
0
 def mock_subroutine_definition(implementation, has_abi_output=False):
     mock = pt.SubroutineDefinition(lambda: pt.Return(pt.Int(1)),
                                    pt.TealType.uint64)
     mock._validate()  # haven't failed with dummy implementation
     mock.implementation = implementation
     mock.has_abi_output = has_abi_output
     return mock
Beispiel #7
0
def test_subroutine_return_value():
    cases = (
        (pt.TealType.uint64, pt.Int(1), pt.Op.int, 1),
        (pt.TealType.bytes, pt.Bytes("value"), pt.Op.byte, '"value"'),
        (pt.TealType.anytype, pt.Int(1), pt.Op.int, 1),
        (pt.TealType.anytype, pt.Bytes("value"), pt.Op.byte, '"value"'),
    )

    for (tealType, value, op, opValue) in cases:
        expr = pt.Return(value)

        def mySubroutine():
            return expr

        subroutine = pt.SubroutineDefinition(mySubroutine, tealType)

        assert expr.type_of() == pt.TealType.none
        assert expr.has_return()

        expected = pt.TealSimpleBlock(
            [pt.TealOp(value, op, opValue), pt.TealOp(expr, pt.Op.retsub)]
        )

        options.setSubroutine(subroutine)
        actual, _ = expr.__teal__(options)
        options.setSubroutine(None)

        actual.addIncoming()
        actual = pt.TealBlock.NormalizeBlocks(actual)

        assert actual == expected
Beispiel #8
0
def test_pragma_expr_has_return():
    exprWithReturn = pt.Pragma(pt.Return(pt.Int(1)),
                               compiler_version=">=0.0.0")
    assert exprWithReturn.has_return()

    exprWithoutReturn = pt.Pragma(pt.Int(1), compiler_version=">=0.0.0")
    assert not exprWithoutReturn.has_return()
Beispiel #9
0
 def fn_mixed_annotation_1(
         a: pt.ScratchVar, b: pt.abi.StaticArray[pt.abi.Uint32,
                                                 Literal[10]]) -> pt.Expr:
     return pt.Seq(
         (intermediate := pt.abi.Uint32()).set(b[a.load() % pt.Int(10)]),
         a.store(intermediate.get()),
         pt.Return(),
     )
Beispiel #10
0
def test_evaluate_subroutine_2_args():
    cases = (
        (pt.TealType.none, pt.Return()),
        (pt.TealType.uint64, pt.Int(1) + pt.Int(2)),
        (pt.TealType.uint64, pt.Return(pt.Int(1) + pt.Int(2))),
        (pt.TealType.bytes, pt.Bytes("value")),
        (pt.TealType.bytes, pt.Return(pt.Bytes("value"))),
    )

    for (returnType, returnValue) in cases:
        argSlots: List[pt.ScratchSlot] = []

        def mySubroutine(a1, a2):
            assert isinstance(a1, pt.ScratchLoad)
            argSlots.append(a1.slot)
            assert isinstance(a2, pt.ScratchLoad)
            argSlots.append(a2.slot)
            return returnValue

        definition = pt.SubroutineDefinition(mySubroutine, returnType)

        declaration = evaluate_subroutine(definition)

        assert isinstance(declaration, pt.SubroutineDeclaration)
        assert declaration.subroutine is definition

        assert declaration.type_of() == returnValue.type_of()
        assert declaration.has_return() == returnValue.has_return()

        assert isinstance(declaration.body, pt.Seq)
        assert len(declaration.body.args) == 3

        assert isinstance(declaration.body.args[0], pt.ScratchStackStore)
        assert isinstance(declaration.body.args[1], pt.ScratchStackStore)

        assert declaration.body.args[0].slot is argSlots[-1]
        assert declaration.body.args[1].slot is argSlots[-2]

        options.setSubroutine(definition)
        expected, _ = pt.Seq(
            [declaration.body.args[0], declaration.body.args[1],
             returnValue]).__teal__(options)

        actual, _ = declaration.__teal__(options)
        options.setSubroutine(None)
        assert actual == expected
Beispiel #11
0
def test_evaluate_subroutine_10_args():
    cases = (
        (pt.TealType.none, pt.Return()),
        (pt.TealType.uint64, pt.Int(1) + pt.Int(2)),
        (pt.TealType.uint64, pt.Return(pt.Int(1) + pt.Int(2))),
        (pt.TealType.bytes, pt.Bytes("value")),
        (pt.TealType.bytes, pt.Return(pt.Bytes("value"))),
    )

    for (returnType, returnValue) in cases:
        argSlots: List[pt.ScratchSlot] = []

        def mySubroutine(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10):
            for a in (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10):
                assert isinstance(a, pt.ScratchLoad)
                argSlots.append(a.slot)
            return returnValue

        definition = pt.SubroutineDefinition(mySubroutine, returnType)
        declaration = evaluate_subroutine(definition)

        assert isinstance(declaration, pt.SubroutineDeclaration)
        assert declaration.subroutine is definition

        assert declaration.type_of() == returnValue.type_of()
        assert declaration.has_return() == returnValue.has_return()

        assert isinstance(declaration.body, pt.Seq)
        assert len(declaration.body.args) == 11

        for i in range(10):
            assert isinstance(declaration.body.args[i], pt.ScratchStackStore)

        for i in range(10):
            assert declaration.body.args[i].slot is argSlots[-i - 1]

        options.setSubroutine(definition)
        expected, _ = pt.Seq(declaration.body.args[:10] +
                             [returnValue]).__teal__(options)

        actual, _ = declaration.__teal__(options)
        options.setSubroutine(None)
        assert actual == expected
Beispiel #12
0
def test_seq_has_return():
    exprWithReturn = pt.Seq(
        [
            pt.App.localPut(pt.Int(0), pt.Bytes("key1"), pt.Int(1)),
            pt.Return(pt.Int(1)),
        ]
    )
    assert exprWithReturn.has_return()

    exprWithoutReturn = pt.Seq(
        [pt.App.localPut(pt.Int(0), pt.Bytes("key1"), pt.Int(1)), pt.Int(1)]
    )
    assert not exprWithoutReturn.has_return()
Beispiel #13
0
def test_subroutine_return_none_invalid():
    for value in (pt.Int(1), pt.Bytes("value")):
        expr = pt.Return(value)

        def mySubroutine():
            return expr

        subroutine = pt.SubroutineDefinition(mySubroutine, pt.TealType.none)

        options.setSubroutine(subroutine)
        with pytest.raises(pt.TealCompileError):
            expr.__teal__(options)
        options.setSubroutine(None)
Beispiel #14
0
def test_pragma_expr_does_not_change():
    without_pragma = pt.Seq(pt.Pop(pt.Add(pt.Int(1), pt.Int(2))),
                            pt.Return(pt.Int(1)))
    pragma = pt.Pragma(without_pragma, compiler_version=">=0.0.0")

    compiled_with_pragma = pt.compileTeal(pragma,
                                          mode=pt.Mode.Application,
                                          version=6)
    compiled_without_pragma = pt.compileTeal(without_pragma,
                                             mode=pt.Mode.Application,
                                             version=6)

    assert compiled_with_pragma == compiled_without_pragma
Beispiel #15
0
def test_subroutine_declaration():
    cases = (
        (pt.TealType.none, pt.Return()),
        (pt.TealType.uint64, pt.Return(pt.Int(1))),
        (pt.TealType.uint64, pt.Int(1)),
        (pt.TealType.bytes, pt.Bytes("value")),
        (pt.TealType.anytype, pt.App.globalGet(pt.Bytes("key"))),
    )

    for (returnType, value) in cases:

        def mySubroutine():
            return value

        definition = pt.SubroutineDefinition(mySubroutine, returnType)

        declaration = pt.SubroutineDeclaration(definition, value)
        assert declaration.type_of() == value.type_of()
        assert declaration.has_return() == value.has_return()

        options.currentSubroutine = definition
        assert declaration.__teal__(options) == value.__teal__(options)
        options.setSubroutine(None)
Beispiel #16
0
def test_nonce_has_return():
    exprWithReturn = pt.Nonce(
        "base32",
        "7Z5PWO2C6LFNQFGHWKSK5H47IQP5OJW2M3HA2QPXTY3WTNP5NU2MHBW27M",
        pt.Return(pt.Int(1)),
    )
    assert exprWithReturn.has_return()

    exprWithoutReturn = pt.Nonce(
        "base32",
        "7Z5PWO2C6LFNQFGHWKSK5H47IQP5OJW2M3HA2QPXTY3WTNP5NU2MHBW27M",
        pt.Int(1),
    )
    assert not exprWithoutReturn.has_return()
Beispiel #17
0
def test_main_return():
    arg = pt.Int(1)
    expr = pt.Return(arg)
    assert expr.type_of() == pt.TealType.none
    assert expr.has_return()

    expected = pt.TealSimpleBlock(
        [pt.TealOp(arg, pt.Op.int, 1), pt.TealOp(expr, pt.Op.return_)]
    )

    actual, _ = expr.__teal__(options)
    actual.addIncoming()
    actual = pt.TealBlock.NormalizeBlocks(actual)

    assert actual == expected
Beispiel #18
0
def test_many_ifs():
    """
    Test with many pt.If statements to trigger potential corner cases in code generation.
    Previous versions of PyTeal took an exponential time to generate the TEAL code for this PyTEAL.
    """

    sv = pt.ScratchVar(pt.TealType.uint64)
    s = pt.Seq([
        pt.If(
            pt.Int(3 * i) == pt.Int(3 * i),
            sv.store(pt.Int(3 * i + 1)),
            sv.store(pt.Int(3 * i + 2)),
        ) for i in range(30)
    ] + [pt.Return(sv.load())])

    pt.compileTeal(s, mode=pt.Mode.Signature, version=2)
Beispiel #19
0
def test_subroutine_return_value_invalid():
    cases = (
        (pt.TealType.bytes, pt.Int(1)),
        (pt.TealType.uint64, pt.Bytes("value")),
    )

    for (tealType, value) in cases:
        expr = pt.Return(value)

        def mySubroutine():
            return expr

        subroutine = pt.SubroutineDefinition(mySubroutine, tealType)

        options.setSubroutine(subroutine)
        with pytest.raises(pt.TealCompileError):
            expr.__teal__(options)
        options.setSubroutine(None)
Beispiel #20
0
def test_Comment_single_line():
    to_wrap = pt.Int(1)
    comment = "just an int"
    expr = pt.Comment(comment, to_wrap)
    assert type(expr) is pt.Seq
    assert len(expr.args) == 2

    assert type(expr.args[0]) is CommentExpr
    assert expr.args[0].comment == comment

    assert expr.args[1] is to_wrap

    version = 6
    expected_teal = f"""#pragma version {version}
// {comment}
int 1
return"""
    actual_teal = pt.compileTeal(pt.Return(expr),
                                 version=version,
                                 mode=pt.Mode.Application)
    assert actual_teal == expected_teal
Beispiel #21
0
def test_subroutine_return_none():
    expr = pt.Return()

    def mySubroutine():
        return expr

    subroutine = pt.SubroutineDefinition(mySubroutine, pt.TealType.none)

    assert expr.type_of() == pt.TealType.none
    assert expr.has_return()

    expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.retsub)])

    options.setSubroutine(subroutine)
    actual, _ = expr.__teal__(options)
    options.setSubroutine(None)

    actual.addIncoming()
    actual = pt.TealBlock.NormalizeBlocks(actual)

    assert actual == expected
Beispiel #22
0
def test_Comment_multi_line():
    to_wrap = pt.Int(1)
    comment = """just an int
but its really more than that isnt it? an integer here is a uint64 stack type but looking further what does that mean? 
You might say its a 64 bit representation of an element of the set Z and comes from the latin `integer` meaning `whole`
since it has no fractional part. You might also say this run on comment has gone too far. See https://en.wikipedia.org/wiki/Integer for more details 
"""

    comment_parts = [
        "just an int",
        "but its really more than that isnt it? an integer here is a uint64 stack type but looking further what does that mean? ",
        "You might say its a 64 bit representation of an element of the set Z and comes from the latin `integer` meaning `whole`",
        "since it has no fractional part. You might also say this run on comment has gone too far. See https://en.wikipedia.org/wiki/Integer for more details ",
    ]

    expr = pt.Comment(comment, to_wrap)
    assert type(expr) is pt.Seq
    assert len(expr.args) == 5

    for i, part in enumerate(comment_parts):
        arg = expr.args[i]
        assert type(arg) is CommentExpr
        assert arg.comment == part

    assert expr.args[4] is to_wrap

    version = 6
    expected_teal = f"""#pragma version {version}
// just an int
// but its really more than that isnt it? an integer here is a uint64 stack type but looking further what does that mean? 
// You might say its a 64 bit representation of an element of the set Z and comes from the latin `integer` meaning `whole`
// since it has no fractional part. You might also say this run on comment has gone too far. See https://en.wikipedia.org/wiki/Integer for more details 
int 1
return"""
    actual_teal = pt.compileTeal(pt.Return(expr),
                                 version=version,
                                 mode=pt.Mode.Application)

    assert actual_teal == expected_teal
Beispiel #23
0
 def fn_0arg_0ret() -> pt.Expr:
     return pt.Return()
Beispiel #24
0
 def fnReturningExprSubclass(a: pt.ScratchVar, b: pt.Expr) -> pt.Return:
     return pt.Return()
Beispiel #25
0
 def fnWithKeywordArgsWrongKWName(a, *, b: pt.abi.Uint64):
     return pt.Return()
Beispiel #26
0
 def fnWithScratchVarSubclass(a, b: pt.DynamicScratchVar):
     return pt.Return()
Beispiel #27
0
 def fnWithNonExprParamAnnotation(a, b: pt.TealType.uint64):
     return pt.Return()
Beispiel #28
0
 def fnWithNonExprReturnAnnotation(a, b) -> pt.TealType.uint64:
     return pt.Return()
Beispiel #29
0
 def fnWithVariableArgs(a, *b):
     return pt.Return()
Beispiel #30
0
 def fnWithMultipleABIKeywordArgs(a, *, b: pt.abi.Byte, c: pt.abi.Bool):
     return pt.Return()