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 compile_exchange_validator(): from contracts import validator print("Compiling exchange validator application...") validator_approve_teal_code = compileTeal(validator.approval_program(), Mode.Application) compile_response = algod_client.compile(validator_approve_teal_code) validator_approve_code = base64.b64decode(compile_response['result']) VALIDATOR_APPROVE_BYTECODE_LEN = len(validator_approve_code) VALIDATOR_APPROVE_ADDRESS = compile_response['hash'] validator_clear_teal_code = compileTeal(validator.clear_program(), Mode.Application) compile_response = algod_client.compile(validator_clear_teal_code) validator_clear_code = base64.b64decode(compile_response['result']) VALIDATOR_CLEAR_BYTECODE_LEN = len(validator_clear_code) VALIDATOR_CLEAR_ADDRESS = compile_response['hash'] print( f"Exchange Validator | Approval: {VALIDATOR_APPROVE_BYTECODE_LEN}/1024 bytes ({VALIDATOR_APPROVE_ADDRESS}) | Clear: {VALIDATOR_CLEAR_BYTECODE_LEN}/1024 bytes ({VALIDATOR_CLEAR_ADDRESS})" ) with open('./build/validator_approval.teal', 'w') as f: f.write(validator_approve_teal_code) with open('./build/validator_clear.teal', 'w') as f: f.write(validator_clear_teal_code) print() return validator_approve_code, validator_clear_code
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_cannot_set_index_with_dynamic(): with pytest.raises(pt.TealInputError) as tie: pt.compileTeal(should_it_work(), pt.Mode.Application, version=6) assert ( "Only allowed to use ScratchVar objects for setting indices, but was given a" in str(tie))
def compile_exchange_manager(): print("Compiling exchange manager application...") manager_approve_teal_code = compileTeal(manager.approval_program(), Mode.Application) compile_response = algod_client.compile(manager_approve_teal_code) manager_approve_code = base64.b64decode(compile_response['result']) MANAGER_APPROVE_BYTECODE_LEN = len(manager_approve_code) MANAGER_APPROVE_ADDRESS = compile_response['hash'] manager_clear_teal_code = compileTeal(manager.clear_program(), Mode.Application) compile_response = algod_client.compile(manager_clear_teal_code) manager_clear_code = base64.b64decode(compile_response['result']) MANAGER_CLEAR_BYTECODE_LEN = len(manager_clear_code) MANAGER_CLEAR_ADDRESS = compile_response['hash'] print( f"Exchange Manager | Approval: {MANAGER_APPROVE_BYTECODE_LEN}/1024 bytes ({MANAGER_APPROVE_ADDRESS}) | Clear: {MANAGER_CLEAR_BYTECODE_LEN}/1024 bytes ({MANAGER_CLEAR_ADDRESS})" ) with open('./build/manager_approval.teal', 'w') as f: f.write(manager_approve_teal_code) with open('./build/manager_clear.teal', 'w') as f: f.write(manager_clear_teal_code) print() return manager_approve_code, manager_clear_code
def test_pragma_expr(compiler_version, should_error): program = pt.Pragma(pt.Approve(), compiler_version=compiler_version) if should_error: with pytest.raises(pt.TealPragmaError): pt.compileTeal(program, mode=pt.Mode.Application, version=6) else: pt.compileTeal(program, mode=pt.Mode.Application, version=6)
def test_vote(): from examples.application.vote import approval_program, clear_state_program approval = approval_program() clear_state = clear_state_program() # only checking for successful compilation for now pt.compileTeal(approval, mode=pt.Mode.Application, version=2) pt.compileTeal(clear_state, mode=pt.Mode.Application, version=2)
def test_cond(): cond1 = pt.Txn.fee() < pt.Int(2000) cond2 = pt.Txn.amount() > pt.Int(5000) cond3 = pt.Txn.receiver() == pt.Txn.sender() core = pt.Cond( [pt.Global.group_size() == pt.Int(2), cond1], [pt.Global.group_size() == pt.Int(3), cond2], [pt.Global.group_size() == pt.Int(4), cond3], ) pt.compileTeal(core, mode=pt.Mode.Signature, version=2)
def test_optimize_subroutine_with_global_var(): global_var = pt.ScratchVar(pt.TealType.uint64) @pt.Subroutine(pt.TealType.uint64) def add(a1: pt.Expr) -> pt.Expr: return pt.Seq(global_var.store(pt.Int(2)), global_var.load() + a1) program = pt.Seq([ pt.If(pt.Txn.sender() == pt.Global.creator_address()).Then( pt.Pop(add(pt.Int(1)))), global_var.store(pt.Int(5)), pt.Approve(), ]) optimize_options = OptimizeOptions() # unoptimized expected = """#pragma version 4 txn Sender global CreatorAddress == bz main_l2 int 1 callsub add_0 pop main_l2: int 5 store 0 int 1 return // add add_0: store 1 int 2 store 0 load 0 load 1 + retsub """.strip() actual = pt.compileTeal(program, version=4, mode=pt.Mode.Application, optimize=optimize_options) assert actual == expected # optimization should not apply to global vars optimize_options = OptimizeOptions(scratch_slots=True) actual = pt.compileTeal(program, version=4, mode=pt.Mode.Application, optimize=optimize_options) assert actual == expected
def test_user_guide_snippets_bad(snippet_etype_e): snippet, etype_e = snippet_etype_e etype, e = etype_e print( f"Test case function=[{snippet.__name__}]. Expecting error of type {etype} with message <{e}>" ) with pytest.raises(etype) as tie: pt.compileTeal(snippet(), mode=pt.Mode.Application, version=6) assert e in str(tie)
def test_security_token(): from examples.application.security_token import ( approval_program, clear_state_program, ) approval = approval_program() clear_state = clear_state_program() # only checking for successful compilation for now pt.compileTeal(approval, mode=pt.Mode.Application, version=2) pt.compileTeal(clear_state, mode=pt.Mode.Application, version=2)
def test_optimize_subroutine_with_reserved_local_var(): local_var = pt.ScratchVar(pt.TealType.uint64, 0) @pt.Subroutine(pt.TealType.uint64) def add(a1: pt.Expr) -> pt.Expr: return pt.Seq(local_var.store(pt.Int(2)), local_var.load() + a1) program = pt.Seq([ pt.If(pt.Txn.sender() == pt.Global.creator_address()).Then( pt.Pop(add(pt.Int(1)))), pt.Approve(), ]) optimize_options = OptimizeOptions() # unoptimized expected = """#pragma version 4 txn Sender global CreatorAddress == bz main_l2 int 1 callsub add_0 pop main_l2: int 1 return // add add_0: store 1 int 2 store 0 load 0 load 1 + retsub """.strip() actual = pt.compileTeal(program, version=4, mode=pt.Mode.Application, optimize=optimize_options) assert actual == expected # The optimization must skip over the reserved slot id so the expected result # hasn't changed. optimize_options = OptimizeOptions(scratch_slots=True) actual = pt.compileTeal(program, version=4, mode=pt.Mode.Application, optimize=optimize_options) assert actual == expected
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
def compile(self, version: int, assemble_constants: bool = False) -> str: return _MatchMode( app_case=lambda: compileTeal( self.program(), self.mode, version=version, assembleConstants=assemble_constants, ), signature_case=lambda: compileTeal( self.program(), self.mode, version=version, assembleConstants=assemble_constants, ), )(self.mode)
def test_optimize_multi_value(): # note: this is incorrect usage of the app_global_get_ex opcode program = pt.Seq( pt.MultiValue( pt.Op.app_global_get_ex, [pt.TealType.uint64, pt.TealType.uint64], immediate_args=[], args=[pt.Int(0), pt.Int(1)], ).outputReducer(lambda value, hasValue: pt.Pop(value + hasValue)), pt.Approve(), ) optimize_options = OptimizeOptions() # unoptimized expected = """#pragma version 4 int 0 int 1 app_global_get_ex store 1 store 0 load 0 load 1 + pop int 1 return""".strip() actual = pt.compileTeal(program, version=4, mode=pt.Mode.Application, optimize=optimize_options) assert actual == expected # optimized expected = """#pragma version 4 int 0 int 1 app_global_get_ex + pop int 1 return""".strip() optimize_options = OptimizeOptions(scratch_slots=True) actual = pt.compileTeal(program, version=4, mode=pt.Mode.Application, optimize=optimize_options) assert actual == expected
def compile_exchange_escrow(): from contracts import escrow print("Compiling exchange escrow logicsig...") escrow_logicsig_teal_code = compileTeal(escrow.logicsig(), Mode.Application) compile_response = algod_client.compile(escrow_logicsig_teal_code) escrow_logicsig = compile_response['result'] escrow_logicsig_bytes = base64.b64decode(escrow_logicsig) ESCROW_BYTECODE_LEN = len(escrow_logicsig_bytes) ESCROW_ADDRESS = compile_response['hash'] print( f"Exchange Escrow | {ESCROW_BYTECODE_LEN}/1000 bytes ({ESCROW_ADDRESS})" ) with open('./build/escrow.teal', 'w') as f: f.write(escrow_logicsig_teal_code) with open("./build/escrow_logicsig", "w") as f: f.write(escrow_logicsig) print(f"Escrow logicsig compiled with address {ESCROW_ADDRESS}") print() return escrow_logicsig
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)
def test_ecdsa_verify_recovered_pk(): curve = pt.EcdsaCurve.Secp256k1 args = [pt.Bytes("data"), pt.Int(1), pt.Bytes("sigA"), pt.Bytes("sigB")] pubkey = pt.EcdsaRecover(curve, args[0], args[1], args[2], args[3]) expr = pt.EcdsaVerify(curve, args[0], args[2], args[3], 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.int, 1), pt.TealOp(args[2], pt.Op.byte, '"sigA"'), pt.TealOp(args[3], pt.Op.byte, '"sigB"'), pt.TealOp(pubkey, pt.Op.ecdsa_pk_recover, 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]), 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.output_slots[0].load(), pt.Op.load, pubkey.output_slots[0]), pt.TealOp(pubkey.output_slots[1].load(), pt.Op.load, pubkey.output_slots[1]), pt.TealOp(expr, pt.Op.ecdsa_verify, curve.arg_name), ]) actual, _ = expr.__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(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_split(): from examples.signature.split import split program = split() target_path = Path.cwd() / "examples" / "signature" / "split.teal" with open(target_path, "r") as target_file: target = "".join(target_file.readlines()).strip() assert pt.compileTeal(program, mode=pt.Mode.Signature, version=2) == target
def test_dutch_auction(): from examples.signature.dutch_auction import dutch_auction program = dutch_auction() target_path = Path.cwd() / "examples" / "signature" / "dutch_auction.teal" with open(target_path, "r") as target_file: target = "".join(target_file.readlines()).strip() assert pt.compileTeal(program, mode=pt.Mode.Signature, version=2) == target
def test_recurring_swap(): from examples.signature.recurring_swap import recurring_swap program = recurring_swap() target_path = Path.cwd() / "examples" / "signature" / "recurring_swap.teal" with open(target_path, "r") as target_file: target = "".join(target_file.readlines()).strip() assert pt.compileTeal(program, mode=pt.Mode.Signature, version=2) == target
def test_basic_bank(): from examples.signature.basic import bank_for_account program = bank_for_account( "ZZAF5ARA4MEC5PVDOP64JM5O5MQST63Q2KOY2FLYFLXXD3PFSNJJBYAFZM") target_path = Path.cwd() / "examples" / "signature" / "basic.teal" with open(target_path, "r") as target_file: target = "".join(target_file.readlines()).strip() assert pt.compileTeal(program, mode=pt.Mode.Signature, version=3) == target
def test_optimize_dynamic_var(): myvar = pt.DynamicScratchVar() regvar = pt.ScratchVar() program = pt.Seq( regvar.store(pt.Int(1)), myvar.set_index(regvar), regvar.store(pt.Int(2)), pt.Pop(regvar.load()), pt.Approve(), ) optimize_options = OptimizeOptions() # unoptimized expected = """#pragma version 4 int 1 store 1 int 1 store 0 int 2 store 1 load 1 pop int 1 return""".strip() actual = pt.compileTeal(program, version=4, mode=pt.Mode.Application, optimize=optimize_options) assert actual == expected # optimization should not change the code because the candidate slot # is used by the dynamic slot variable. optimize_options = OptimizeOptions(scratch_slots=True) actual = pt.compileTeal(program, version=4, mode=pt.Mode.Application, optimize=optimize_options) assert actual == expected
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
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
Txn.application_args[1], # Signature Txn.sender() # Public key of signer ) ), # Return 1 so the transaction is approved Int(1) ) return Cond( [Txn.application_id() == Int(0), Return(Int(1))], [Txn.on_completion() == OnComplete.DeleteApplication, Return(is_app_creator)], [Txn.on_completion() == OnComplete.UpdateApplication, Return(is_app_creator)], [Txn.on_completion() == OnComplete.CloseOut, Return(Int(1))], [Txn.on_completion() == OnComplete.OptIn, Return(Int(1))], [Txn.application_args.length()>Int(0), Return(verify)], [Txn.application_args.length()==Int(0), Return(Int(1))] ) def clear(): return Return(Int(1)) if __name__ == "__main__": path = os.path.dirname(os.path.abspath(__file__)) with open(os.path.join(path, "approval.teal"), "w") as f: f.write(compileTeal(approval(), mode=Mode.Application, version=5)) with open(os.path.join(path, "clear.teal"), "w") as f: f.write(compileTeal(clear(), mode=Mode.Application, version=5))
Return(price_increase_listing) ], # App validates caller [Txn.application_args[0] == action_delete, Return(delete_listing)], # App approves sender owns listing [Txn.application_args[0] == action_purchase, Return(purchase_listing)], # App removes listing from local state [Txn.application_args[0] == action_safety, Return(delist_listing)] # App removes listing from local state ) def clear(): return Int(1) if __name__ == "__main__": with open(tealpath(configuration['contracts']['approval']), "w") as pa_file: pa_file.write( compileTeal(approval(), Mode.Application, version=4, assembleConstants=True)) with open(tealpath(configuration['contracts']['clear']), "w") as pc_file: pc_file.write( compileTeal(clear(), Mode.Application, version=4, assembleConstants=True))
from pyteal import ScratchVar, Or, TealType, Mode, compileTeal from config import * from utils import * def platform_owner(): #Allow any grouped atomic txns that are approved by the application or the admin _app_id = ScratchVar(TealType.uint64) return And( Global.group_size() > Int(1), Seq([_app_id.store(app_id), Int(1)]), Or(valid_app_call(Gtxn[0], _app_id.load()), valid_admin_fee_pay(Gtxn[0]))) if __name__ == "__main__": with open(tealpath("platform-owner.teal"), 'w') as f: f.write(compileTeal(platform_owner(), Mode.Signature, version=4))
from pyteal import compileTeal, Int, Mode if __name__ == "__main__": print(compileTeal(Int(1), Mode.Application))
set_addr_as_tx( Gtxn[2], contract_addr), pay_txn_valid( Gtxn[1], Gtxn[1].amount(), buyer_addr.load(), creator_addr.load()), asa_close_xfer_valid(Gtxn[2], asset_id.load(), contract_addr.load(), buyer_addr.load(), buyer_addr.load()), asa_close_xfer_valid(Gtxn[3], _price_token.load(), contract_addr.load(), platform_addr, platform_addr), asa_cfg_valid( Gtxn[4], asset_id.load(), buyer_addr.load()), # Possible Tag closes pay_close_txn_valid( Gtxn[Global.group_size() - Int(1)], contract_addr.load(), platform_addr, creator_addr.load(), platform_fee), ) app_offload = Or( Gtxn[0].application_args[0] == action_tag, Gtxn[0].application_args[0] == action_untag, Gtxn[0].application_args[0] == action_dprice, Gtxn[0].application_args[0] == action_safety ) app_validate = valid_app_call(Gtxn[0], _app_id.load()) return Cond([setup, Int(0)], #NoOp [Gtxn[0].application_args[0] == action_create, create], [Gtxn[0].application_args[0] == action_delete, delete], [Gtxn[0].application_args[0] == action_purchase, purchase], [app_offload, app_validate]) if __name__ == "__main__": with open(tealpath(configuration['contracts']['listing']), 'w') as f: f.write(compileTeal(listing(), Mode.Signature, version=4, assembleConstants=True))