def test_String_set_expr(): for value_to_set in (pt.Bytes("hi"), pt.Bytes("base16", "0xdeadbeef")): value = abi.String() expr = value.set(value_to_set) assert expr.type_of() == pt.TealType.none assert not expr.has_return() value_start, value_end = value_to_set.__teal__(options) expected_body = pt.TealSimpleBlock([ pt.TealOp(None, pt.Op.store, value.stored_value.slot), pt.TealOp(None, pt.Op.load, value.stored_value.slot), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), pt.TealOp(None, pt.Op.extract, 6, 0), pt.TealOp(None, pt.Op.load, value.stored_value.slot), pt.TealOp(None, pt.Op.concat), pt.TealOp(None, pt.Op.store, value.stored_value.slot), ]) value_end.setNextBlock(expected_body) expected = value_start 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_ecdsa_verify_basic(curve: pt.EcdsaCurve): args = [pt.Bytes("data"), pt.Bytes("sigA"), pt.Bytes("sigB")] pubkey = (pt.Bytes("X"), pt.Bytes("Y")) expr = pt.EcdsaVerify(curve, args[0], args[1], args[2], pubkey) assert expr.type_of() == pt.TealType.uint64 expected = pt.TealSimpleBlock([ pt.TealOp(args[0], pt.Op.byte, '"data"'), pt.TealOp(args[1], pt.Op.byte, '"sigA"'), pt.TealOp(args[2], pt.Op.byte, '"sigB"'), pt.TealOp(pubkey[0], pt.Op.byte, '"X"'), pt.TealOp(pubkey[1], pt.Op.byte, '"Y"'), pt.TealOp(expr, pt.Op.ecdsa_verify, curve.arg_name), ]) actual, _ = expr.__teal__(curve_options_map[curve]) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected # compile without errors this is necessary so assembly is also tested pt.compileTeal( pt.Seq(pt.Pop(expr), pt.Approve()), pt.Mode.Application, version=curve.min_version, ) with pytest.raises(pt.TealInputError): pt.compileTeal( pt.Seq(pt.Pop(expr), pt.Approve()), pt.Mode.Application, version=curve.min_version - 1, )
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_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_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_StaticBytes_expr(test_case: bytes | bytearray): value: abi.StaticBytes = abi.StaticBytes( abi.StaticBytesTypeSpec(len(test_case) * 2)) set_expr = pt.Concat(pt.Bytes(test_case), pt.Bytes(test_case)) expr = value.set(set_expr) assert expr.type_of() == pt.TealType.none assert not expr.has_return() actual, _ = expr.__teal__(options) actual.addIncoming() actual = actual.NormalizeBlocks(actual) expected = pt.TealSimpleBlock([ pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), pt.TealOp(None, pt.Op.concat), pt.TealOp(None, pt.Op.store, value.stored_value.slot), pt.TealOp(None, pt.Op.int, 32), pt.TealOp(None, pt.Op.load, value.stored_value.slot), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.eq), pt.TealOp(None, pt.Op.assert_), ]) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == 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_StaticArray_set_computed(): value = abi.StaticArray(abi.StaticArrayTypeSpec(abi.Uint64TypeSpec(), 10)) computed = ContainerType(value.type_spec(), pt.Bytes("indeed this is hard to simulate")) expr = value.set(computed) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expected = pt.TealSimpleBlock([ pt.TealOp(None, pt.Op.byte, '"indeed this is hard to simulate"'), pt.TealOp(None, pt.Op.store, value.stored_value.slot), ]) actual, _ = expr.__teal__(options) actual.addIncoming() actual = actual.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected with pytest.raises(pt.TealInputError): value.set( ContainerType( abi.StaticArrayTypeSpec(abi.Uint16TypeSpec(), 40), pt.Bytes("well i am trolling"), ))
def test_Tuple_set_Computed(): tupleValue = abi.Tuple( abi.TupleTypeSpec( abi.Uint8TypeSpec(), abi.Uint16TypeSpec(), abi.Uint32TypeSpec() ) ) computed = ContainerType( tupleValue.type_spec(), pt.Bytes("internal representation") ) expr = tupleValue.set(computed) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, '"internal representation"'), pt.TealOp(None, pt.Op.store, tupleValue.stored_value.slot), ] ) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected with pytest.raises(pt.TealInputError): tupleValue.set(computed, computed) with pytest.raises(pt.TealInputError): tupleValue.set( ContainerType(abi.TupleTypeSpec(abi.ByteTypeSpec()), pt.Bytes(b"a")) )
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_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)))
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_set_byte_invalid(): with pytest.raises(pt.TealTypeError): pt.SetByte(pt.Int(3), pt.Int(0), pt.Int(1)) with pytest.raises(pt.TealTypeError): pt.SetByte(pt.Bytes("base16", "0xFF"), pt.Bytes("index"), pt.Int(1)) with pytest.raises(pt.TealTypeError): pt.SetByte(pt.Bytes("base16", "0xFF"), pt.Int(0), pt.Bytes("one"))
def test_divw_invalid(): with pytest.raises(pt.TealTypeError): pt.Divw(pt.Bytes("10"), pt.Int(0), pt.Int(1)) with pytest.raises(pt.TealTypeError): pt.Divw(pt.Int(10), pt.Bytes("0"), pt.Int(1)) with pytest.raises(pt.TealTypeError): pt.Divw(pt.Int(10), pt.Int(0), pt.Bytes("1"))
def test_extract_invalid(): with pytest.raises(pt.TealTypeError): pt.Extract(pt.Int(0), pt.Int(0), pt.Int(2)) with pytest.raises(pt.TealTypeError): pt.Extract(pt.Bytes("my string"), pt.Txn.sender(), pt.Int(2)) with pytest.raises(pt.TealTypeError): pt.Extract(pt.Bytes("my string"), pt.Int(0), pt.Txn.sender())
def test_substring_invalid(): with pytest.raises(pt.TealTypeError): pt.Substring(pt.Int(0), pt.Int(0), pt.Int(2)) with pytest.raises(pt.TealTypeError): pt.Substring(pt.Bytes("my string"), pt.Txn.sender(), pt.Int(2)) with pytest.raises(pt.TealTypeError): pt.Substring(pt.Bytes("my string"), pt.Int(0), pt.Txn.sender()) with pytest.raises(Exception): pt.Substring(pt.Bytes("my string"), pt.Int(1), pt.Int(0)).__teal__(avm5Options)
def swapper(): a = pt.ScratchVar(pt.TealType.bytes) b = pt.ScratchVar(pt.TealType.bytes) return pt.Seq( a.store(pt.Bytes("hello")), b.store(pt.Bytes("goodbye")), cat(a.load(), b.load()), swap(a, b), pt.Assert(a.load() == pt.Bytes("goodbye")), pt.Assert(b.load() == pt.Bytes("hello")), pt.Int(1000), )
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()
def test_seq_overloads_equivalence(): items = [ pt.App.localPut(pt.Int(0), pt.Bytes("key1"), pt.Int(1)), pt.App.localPut(pt.Int(1), pt.Bytes("key2"), pt.Bytes("value2")), pt.Pop(pt.Bytes("end")), ] expr1 = pt.Seq(items) expr2 = pt.Seq(*items) expected = expr1.__teal__(options) actual = expr2.__teal__(options) assert actual == expected
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()
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()
def test_ecdsa_decompress(curve: pt.EcdsaCurve): compressed_pubkey = pt.Bytes("XY") pubkey = pt.EcdsaDecompress(curve, compressed_pubkey) assert pubkey.type_of() == pt.TealType.none expected = pt.TealSimpleBlock([ pt.TealOp(compressed_pubkey, pt.Op.byte, '"XY"'), pt.TealOp(pubkey, pt.Op.ecdsa_pk_decompress, curve.arg_name), pt.TealOp(pubkey.output_slots[1].store(), pt.Op.store, pubkey.output_slots[1]), pt.TealOp(pubkey.output_slots[0].store(), pt.Op.store, pubkey.output_slots[0]), ]) actual, _ = pubkey.__teal__(curve_options_map[curve]) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected # compile without errors this is necessary so assembly is also tested pt.compileTeal(pt.Seq(pubkey, pt.Approve()), pt.Mode.Application, version=curve.min_version) with pytest.raises(pt.TealInputError): pt.compileTeal( pt.Seq(pubkey, pt.Approve()), pt.Mode.Application, version=curve.min_version - 1, )
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)))
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_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_extract_uint(): for expression, op in ( (pt.ExtractUint16, pt.Op.extract_uint16), (pt.ExtractUint32, pt.Op.extract_uint32), (pt.ExtractUint64, pt.Op.extract_uint64), ): args = [ pt.Bytes("base16", "0xFFFFFFFFFFFFFFFFFF"), pt.Int(2), ] expr = expression(args[0], args[1]) assert expr.type_of() == pt.TealType.uint64 expected = pt.TealSimpleBlock([ pt.TealOp(args[0], pt.Op.byte, "0xFFFFFFFFFFFFFFFFFF"), pt.TealOp(args[1], pt.Op.int, 2), pt.TealOp(expr, op), ]) actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): expr.__teal__(avm4Options)
def test_extract_uint_invalid(): for expression in (pt.ExtractUint16, pt.ExtractUint32, pt.ExtractUint64): with pytest.raises(pt.TealTypeError): expression(pt.Int(2), pt.Txn.receiver()) with pytest.raises(pt.TealTypeError): expression(pt.Bytes("base16", "0xFF"), pt.Txn.receiver())
def test_concat_two(): args = [pt.Bytes("a"), pt.Bytes("b")] expr = pt.Concat(args[0], args[1]) assert expr.type_of() == pt.TealType.bytes expected = pt.TealSimpleBlock([ pt.TealOp(args[0], pt.Op.byte, '"a"'), pt.TealOp(args[1], pt.Op.byte, '"b"'), pt.TealOp(expr, pt.Op.concat), ]) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected
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_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