def test_scratchvar_type(): myvar_default = pt.ScratchVar() assert myvar_default.storage_type() == pt.TealType.anytype assert myvar_default.store(pt.Bytes("value")).type_of() == pt.TealType.none assert myvar_default.load().type_of() == pt.TealType.anytype with pytest.raises(pt.TealTypeError): myvar_default.store(pt.Pop(pt.Int(1))) myvar_int = pt.ScratchVar(pt.TealType.uint64) assert myvar_int.storage_type() == pt.TealType.uint64 assert myvar_int.store(pt.Int(1)).type_of() == pt.TealType.none assert myvar_int.load().type_of() == pt.TealType.uint64 with pytest.raises(pt.TealTypeError): myvar_int.store(pt.Bytes("value")) with pytest.raises(pt.TealTypeError): myvar_int.store(pt.Pop(pt.Int(1))) myvar_bytes = pt.ScratchVar(pt.TealType.bytes) assert myvar_bytes.storage_type() == pt.TealType.bytes assert myvar_bytes.store(pt.Bytes("value")).type_of() == pt.TealType.none assert myvar_bytes.load().type_of() == pt.TealType.bytes with pytest.raises(pt.TealTypeError): myvar_bytes.store(pt.Int(0)) with pytest.raises(pt.TealTypeError): myvar_bytes.store(pt.Pop(pt.Int(1)))
def test_Uint_decode(): encoded = pt.Bytes("encoded") for test in testData: for start_index in (None, pt.Int(1)): for end_index in (None, pt.Int(2)): for length in (None, pt.Int(3)): value = test.uintType.new_instance() expr = value.decode( encoded, start_index=start_index, end_index=end_index, length=length, ) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expectedDecoding = value.stored_value.store( test.expectedDecoding(encoded, start_index, end_index, length)) expected, _ = expectedDecoding.__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 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()
def test_Uint_set_expr(): for test in testData: value = test.uintType.new_instance() expr = value.set(pt.Int(10) + pt.Int(1)) assert expr.type_of() == pt.TealType.none assert not expr.has_return() upperBoundCheck = [] if test.checkUpperBound: upperBoundCheck = [ pt.TealOp(None, pt.Op.load, value.stored_value.slot), pt.TealOp(None, pt.Op.int, test.maxValue + 1), pt.TealOp(None, pt.Op.lt), pt.TealOp(None, pt.Op.assert_), ] expected = pt.TealSimpleBlock([ pt.TealOp(None, pt.Op.int, 10), pt.TealOp(None, pt.Op.int, 1), pt.TealOp(None, pt.Op.add), pt.TealOp(None, pt.Op.store, value.stored_value.slot), ] + upperBoundCheck) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected
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
def test_neq_overload(): args_int = [pt.Int(2), pt.Int(3)] expr_int = args_int[0] != args_int[1] assert expr_int.type_of() == pt.TealType.uint64 expected_int = pt.TealSimpleBlock([ pt.TealOp(args_int[0], pt.Op.int, 2), pt.TealOp(args_int[1], pt.Op.int, 3), pt.TealOp(expr_int, pt.Op.neq), ]) actual_int, _ = expr_int.__teal__(avm2Options) actual_int.addIncoming() actual_int = pt.TealBlock.NormalizeBlocks(actual_int) assert actual_int == expected_int args_bytes = [pt.Txn.receiver(), pt.Txn.sender()] expr_bytes = args_bytes[0] != args_bytes[1] assert expr_bytes.type_of() == pt.TealType.uint64 expected_bytes = pt.TealSimpleBlock([ pt.TealOp(args_bytes[0], pt.Op.txn, "Receiver"), pt.TealOp(args_bytes[1], pt.Op.txn, "Sender"), pt.TealOp(expr_bytes, pt.Op.neq), ]) actual_bytes, _ = expr_bytes.__teal__(avm2Options) actual_bytes.addIncoming() actual_bytes = pt.TealBlock.NormalizeBlocks(actual_bytes) assert actual_bytes == expected_bytes
def test_ReferenceType_decode(): encoded = pt.Bytes("encoded") for value in (abi.Account(), abi.Asset(), abi.Application()): for start_index in (None, pt.Int(1)): for end_index in (None, pt.Int(2)): for length in (None, pt.Int(3)): expr = value.decode( encoded, start_index=start_index, end_index=end_index, length=length, ) assert expr.type_of() == pt.TealType.none assert expr.has_return() is False expected_decoding = value.stored_value.store( pt.GetByte( encoded, start_index if start_index is not None else pt.Int(0), )) expected, _ = expected_decoding.__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 test_gtxna_expr_valid(): [ e.__teal__(avm6Options) for e in [ pt.GtxnaExpr(1, pt.TxnField.assets, 1), pt.GtxnaExpr(pt.Int(1), pt.TxnField.assets, pt.Int(1)), ] ]
def test_replace_stack_not_int(): my_string = "*" * 257 add = pt.Add(pt.Int(254), pt.Int(2)) args = [pt.Bytes(my_string), add, pt.Bytes("ab")] expr = pt.Replace(args[0], args[1], args[2]) assert expr.type_of() == pt.TealType.bytes expected = pt.TealSimpleBlock([ pt.TealOp(args[0], pt.Op.byte, '"{my_string}"'.format(my_string=my_string)), pt.TealOp(pt.Int(254), pt.Op.int, 254), pt.TealOp(pt.Int(2), pt.Op.int, 2), pt.TealOp(add, pt.Op.add), pt.TealOp(args[2], pt.Op.byte, '"ab"'), pt.TealOp(expr, pt.Op.replace3), ]) actual, _ = expr.__teal__(avm7Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected with pytest.raises(pt.TealInputError): expr.__teal__(avm6Options)
def test_subroutine_call(): def mySubroutine(): return pt.Return() returnTypes = ( pt.TealType.uint64, pt.TealType.bytes, pt.TealType.anytype, pt.TealType.none, ) argCases = ( [], [pt.Int(1)], [pt.Int(1), pt.Bytes("value")], ) for returnType in returnTypes: definition = pt.SubroutineDefinition(mySubroutine, returnType) for args in argCases: expr = pt.SubroutineCall(definition, args) assert expr.type_of() == returnType assert not expr.has_return() expected, _ = pt.TealBlock.FromOp( options, pt.TealOp(expr, pt.Op.callsub, definition), *args) actual, _ = expr.__teal__(options) assert actual == expected
def test_while_compiles(): i = pt.ScratchVar() expr = pt.While(pt.Int(2)).Do(pt.Seq([i.store(pt.Int(0))])) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expr.__teal__(options)
def test_decorator(): assert callable(pt.Subroutine) assert callable(pt.Subroutine(pt.TealType.anytype)) @pt.Subroutine(pt.TealType.none) def mySubroutine(a): return pt.Return() assert isinstance(mySubroutine, pt.SubroutineFnWrapper) invocation = mySubroutine(pt.Int(1)) assert isinstance(invocation, pt.SubroutineCall) with pytest.raises(pt.TealInputError): mySubroutine() with pytest.raises(pt.TealInputError): mySubroutine(pt.Int(1), pt.Int(2)) with pytest.raises(pt.TealInputError): mySubroutine(pt.Pop(pt.Int(1))) with pytest.raises(pt.TealInputError): mySubroutine(1) with pytest.raises(pt.TealInputError): mySubroutine(a=pt.Int(1))
def test_AssetParamObject(): for asset in (pt.Int(1), pt.Int(100)): obj = pt.AssetParamObject(asset) assert obj._asset is asset assert_MaybeValue_equality(obj.total(), pt.AssetParam.total(asset), avm5Options) assert_MaybeValue_equality(obj.decimals(), pt.AssetParam.decimals(asset), avm5Options) assert_MaybeValue_equality(obj.default_frozen(), pt.AssetParam.defaultFrozen(asset), avm5Options) assert_MaybeValue_equality(obj.unit_name(), pt.AssetParam.unitName(asset), avm5Options) assert_MaybeValue_equality(obj.name(), pt.AssetParam.name(asset), avm5Options) assert_MaybeValue_equality(obj.url(), pt.AssetParam.url(asset), avm5Options) assert_MaybeValue_equality(obj.metadata_hash(), pt.AssetParam.metadataHash(asset), avm5Options) assert_MaybeValue_equality(obj.manager_address(), pt.AssetParam.manager(asset), avm5Options) assert_MaybeValue_equality(obj.reserve_address(), pt.AssetParam.reserve(asset), avm5Options) assert_MaybeValue_equality(obj.freeze_address(), pt.AssetParam.freeze(asset), avm5Options) assert_MaybeValue_equality(obj.clawback_address(), pt.AssetParam.clawback(asset), avm5Options) assert_MaybeValue_equality(obj.creator_address(), pt.AssetParam.creator(asset), avm5Options)
def test_while_invalid(): with pytest.raises(TypeError): expr = pt.While() with pytest.raises(pt.TealCompileError): expr = pt.While(pt.Int(2)) expr.type_of() with pytest.raises(pt.TealCompileError): expr = pt.While(pt.Int(2)) expr.__teal__(options) with pytest.raises(pt.TealCompileError): expr = pt.While(pt.Int(2)) expr.type_of() with pytest.raises(pt.TealCompileError): expr = pt.While(pt.Int(2)) expr.__str__() with pytest.raises(pt.TealTypeError): expr = pt.While(pt.Int(2)).Do(pt.Int(2)) with pytest.raises(pt.TealTypeError): expr = pt.While(pt.Int(2)).Do(pt.Pop(pt.Int(2)), pt.Int(2)) with pytest.raises(pt.TealCompileError): expr = pt.While(pt.Int(0)).Do(pt.Continue()).Do(pt.Continue()) expr.__str__()
def test_ComputedType_use(): for value in (0, 1, 2, 3, 12345): dummyComputedType = ContainerType(abi.Uint64TypeSpec(), pt.Int(value)) expr = dummyComputedType.use(lambda output: pt.Int(2) * output.get()) assert expr.type_of() == pt.TealType.uint64 assert not expr.has_return() actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert type(actual) is pt.TealSimpleBlock assert actual.ops[1].op == pt.Op.store assert type(actual.ops[1].args[0]) is pt.ScratchSlot actualSlot = actual.ops[1].args[0] expected = pt.TealSimpleBlock([ pt.TealOp(None, pt.Op.int, value), pt.TealOp(None, pt.Op.store, actualSlot), pt.TealOp(None, pt.Op.int, 2), pt.TealOp(None, pt.Op.load, actualSlot), pt.TealOp(None, pt.Op.mul), ]) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected
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
def test_Bool_decode(): value = abi.Bool() encoded = pt.Bytes("encoded") for start_index in (None, pt.Int(1)): for end_index in (None, pt.Int(2)): for length in (None, pt.Int(3)): expr = value.decode(encoded, start_index=start_index, end_index=end_index, length=length) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expected = pt.TealSimpleBlock([ pt.TealOp(None, pt.Op.byte, '"encoded"'), pt.TealOp(None, pt.Op.int, 0 if start_index is None else 1), pt.TealOp(None, pt.Op.int, 8), pt.TealOp(None, pt.Op.mul), pt.TealOp(None, pt.Op.getbit), 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 test_while_break(): i = pt.ScratchVar() i.store(pt.Int(0)) items = [ i.load() < pt.Int(2), i.store(i.load() + pt.Int(1)), pt.If(i.load() == pt.Int(1), pt.Break()), ] expr = pt.While(items[0]).Do(pt.Seq(items[1], items[2])) assert expr.type_of() == pt.TealType.none assert not expr.has_return() options.enterLoop() expected, condEnd = items[0].__teal__(options) do, doEnd = pt.Seq([items[1], items[2]]).__teal__(options) expectedBranch = pt.TealConditionalBlock([]) end = pt.TealSimpleBlock([]) expectedBranch.setTrueBlock(do) expectedBranch.setFalseBlock(end) condEnd.setNextBlock(expectedBranch) doEnd.setNextBlock(expected) breakBlocks, _ = options.exitLoop() for block in breakBlocks: block.setNextBlock(end) actual, _ = expr.__teal__(options) assert actual == expected
def test_AppParamObject(): for app in (pt.Int(1), pt.Int(100)): obj = pt.AppParamObject(app) assert obj._app is app assert_MaybeValue_equality(obj.approval_program(), pt.AppParam.approvalProgram(app), avm5Options) assert_MaybeValue_equality(obj.clear_state_program(), pt.AppParam.clearStateProgram(app), avm5Options) assert_MaybeValue_equality(obj.global_num_uint(), pt.AppParam.globalNumUint(app), avm5Options) assert_MaybeValue_equality( obj.global_num_byte_slice(), pt.AppParam.globalNumByteSlice(app), avm5Options, ) assert_MaybeValue_equality(obj.local_num_uint(), pt.AppParam.localNumUint(app), avm5Options) assert_MaybeValue_equality(obj.local_num_byte_slice(), pt.AppParam.localNumByteSlice(app), avm5Options) assert_MaybeValue_equality(obj.extra_program_pages(), pt.AppParam.extraProgramPages(app), avm5Options) assert_MaybeValue_equality(obj.creator_address(), pt.AppParam.creator(app), avm5Options) assert_MaybeValue_equality(obj.address(), pt.AppParam.address(app), avm5Options)
def test_wrap_handler_method_txn_types(): wrapped: pt.Expr = ASTBuilder.wrap_handler(True, multiple_txn) actual: pt.TealBlock = assemble_helper(wrapped) args: list[pt.abi.Transaction] = [ pt.abi.ApplicationCallTransaction(), pt.abi.AssetTransferTransaction(), pt.abi.PaymentTransaction(), pt.abi.Transaction(), ] output_temp = pt.abi.Uint64() expected_ast = pt.Seq( args[0]._set_index(pt.Txn.group_index() - pt.Int(4)), pt.Assert(args[0].get().type_enum() == pt.TxnType.ApplicationCall), args[1]._set_index(pt.Txn.group_index() - pt.Int(3)), pt.Assert(args[1].get().type_enum() == pt.TxnType.AssetTransfer), args[2]._set_index(pt.Txn.group_index() - pt.Int(2)), pt.Assert(args[2].get().type_enum() == pt.TxnType.Payment), args[3]._set_index(pt.Txn.group_index() - pt.Int(1)), multiple_txn(*args).store_into(output_temp), pt.abi.MethodReturn(output_temp), pt.Approve(), ) expected = assemble_helper(expected_ast) with pt.TealComponent.Context.ignoreScratchSlotEquality(), pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected assert pt.TealBlock.MatchScratchSlotReferences( pt.TealBlock.GetReferencedScratchSlots(actual), pt.TealBlock.GetReferencedScratchSlots(expected), )
def test_cond_two_pred(): expr = pt.Cond([pt.Int(1), pt.Bytes("one")], [pt.Int(0), pt.Bytes("zero")]) assert expr.type_of() == pt.TealType.bytes cond1, _ = pt.Int(1).__teal__(options) pred1, _ = pt.Bytes("one").__teal__(options) cond1Branch = pt.TealConditionalBlock([]) cond2, _ = pt.Int(0).__teal__(options) pred2, _ = pt.Bytes("zero").__teal__(options) cond2Branch = pt.TealConditionalBlock([]) end = pt.TealSimpleBlock([]) cond1.setNextBlock(cond1Branch) cond1Branch.setTrueBlock(pred1) cond1Branch.setFalseBlock(cond2) pred1.setNextBlock(end) cond2.setNextBlock(cond2Branch) cond2Branch.setTrueBlock(pred2) cond2Branch.setFalseBlock(pt.Err().__teal__(options)[0]) pred2.setNextBlock(end) expected = cond1 actual, _ = expr.__teal__(options) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected
def test_for(): i = pt.ScratchVar() items = [ (i.store(pt.Int(0))), i.load() < pt.Int(10), i.store(i.load() + pt.Int(1)), pt.App.globalPut(pt.Itob(i.load()), i.load() * pt.Int(2)), ] expr = pt.For(items[0], items[1], items[2]).Do(pt.Seq([items[3]])) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expected, varEnd = items[0].__teal__(options) condStart, condEnd = items[1].__teal__(options) stepStart, stepEnd = items[2].__teal__(options) do, doEnd = pt.Seq([items[3]]).__teal__(options) expectedBranch = pt.TealConditionalBlock([]) end = pt.TealSimpleBlock([]) varEnd.setNextBlock(condStart) doEnd.setNextBlock(stepStart) expectedBranch.setTrueBlock(do) expectedBranch.setFalseBlock(end) condEnd.setNextBlock(expectedBranch) stepEnd.setNextBlock(condStart) actual, _ = expr.__teal__(options) assert actual == expected
def test_use_seq_if_multiple_overloads_equivalence(): items = [pt.Pop(pt.Int(1)), pt.Int(2)] expr = _use_seq_if_multiple(items) expected = pt.Seq(items).__teal__(options) actual = expr.__teal__(options) assert actual == expected
def factorial_BAD(n: pt.ScratchVar): tmp = pt.ScratchVar(pt.TealType.uint64) return (pt.If(n.load() <= pt.Int(1)).Then(n.store(pt.Int(1))).Else( pt.Seq( tmp.store(n.load() - pt.Int(1)), factorial_BAD(tmp), n.store(n.load() * tmp.load()), )))
def test_continue_break(): i = pt.ScratchVar() expr = pt.For(i.store(pt.Int(0)), pt.Int(1), i.store(i.load() + pt.Int(1))).Do( pt.Seq([pt.If(pt.Int(1), pt.Break(), pt.Continue())]) ) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expr.__teal__(options)
def subr_string_mult(s: pt.ScratchVar, n): tmp = pt.ScratchVar(pt.TealType.bytes) return (pt.If(n == pt.Int(0)).Then(s.store(pt.Bytes(""))).Else( pt.Seq( tmp.store(s.load()), subr_string_mult(s, n - pt.Int(1)), s.store(pt.Concat(s.load(), tmp.load())), )))
def plus_one(n: pt.ScratchVar): tmp = pt.ScratchVar(pt.TealType.uint64) return (pt.If(n.load() == pt.Int(0)).Then(n.store(pt.Int(1))).Else( pt.Seq( tmp.store(n.load() - pt.Int(1)), plus_one(tmp), n.store(tmp.load() + pt.Int(1)), )))
def sub_logcat_dynamic(): first = pt.ScratchVar(pt.TealType.bytes) return pt.Seq( first.store(pt.Bytes("hello")), logcat_dynamic(first, pt.Int(42)), pt.Assert(pt.Bytes("hello42") == first.load()), pt.Int(1), )
def test_for_compiles(): i = pt.ScratchVar() expr = pt.For(i.store(pt.Int(0)), pt.Int(1), i.store(i.load() + pt.Int(1))).Do( pt.App.globalPut(pt.Itob(pt.Int(0)), pt.Itob(pt.Int(2))) ) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expr.__teal__(options)
def test_gload_teal_3(): with pytest.raises(pt.TealInputError): pt.ImportScratchValue(0, 1).__teal__(avm3Options) with pytest.raises(pt.TealInputError): pt.ImportScratchValue(pt.Int(0), 1).__teal__(avm3Options) with pytest.raises(pt.TealInputError): pt.ImportScratchValue(pt.Int(0), pt.Int(1)).__teal__(avm3Options)