Recipes¶
Converting App Argument to Integer¶
All arguments passed to the application in the ApplicationCall transaction are converted to bytes. If you passed an integer and want to use it as integer in the contract, you have to convert it to integer using btoi opcode.
1bytes input_as_bytes = Txn.ApplicationArgs[0]
2int input_as_int = btoi(input_as_bytes)
3
4# Example: Total sum of all app arguments
5int app_args_count = Txn.NumAppArgs
6int total = 0
7
8for index in 0:app_args_count:
9 total = total + btoi(Txn.ApplicationArgs[index])
10end
Opting in the application to an asset¶
1int asset_id
2
3int is_opted_in
4is_opted_in, _ = asset_holding_get(AssetBalance, Global.CurrentApplicationAddress, asset_id)
5
6if is_opted_in == 0:
7 inner_txn:
8 TypeEnum: Axfer
9 Sender: Global.CurrentApplicationAddress
10 AssetReceiver: Global.CurrentApplicationAddress
11 AssetAmount: 0
12 XferAsset: asset_id
13 Fee: 0
14 end
15end
Inner app call¶
1inner_txn:
2 TypeEnum: Appl
3 OnCompletion: NoOp
4 ApplicationID: THE_APP_ID
5 ApplicationArgs[0]: "arg1"
6 ApplicationArgs[1]: "arg2"
7 Accounts[0]: Txn.Sender
8 Accounts[1]: Txn.Accounts[1]
9 Fee: 0
10end
Calling another application with an inner transaction¶
1inner_txn:
2 TypeEnum: Appl
3 OnCompletion: NoOp
4 ApplicationID: THE_APP_ID
5 ApplicationArgs[0]: "arg1"
6 ApplicationArgs[1]: "arg2"
7 Accounts[0]: Txn.Sender
8 Accounts[1]: Txn.Accounts[1]
9 Fee: 0
10end
Handling Integer Overflow¶
Converting integers to big-endian unsigned integers and using
byte arithmetics
allows handling integers up to 512 bits without overflow. Note that these b*
and others have a higher opcode cost than the normal integer operators.
1const int MAX_INT_64 = 18446744073709551615
2
3# a and b are very big numbers and multiplication of them doesn't fit in to uint 64.
4int a = MAX_INT_64
5int b = MAX_INT_64 / 2
6
7bytes mul = itob(a) b* itob(b)
8bytes sum = itob(a) b+ itob(b)
9int result = btoi(mul b/ sum)
Optimizing the generated TEAL code partially¶
Teal allows using raw TEAL directly, see Inline Teal. Decreasing the size and computational cost using TEAL and custom stack management is possible.
Reformatting the Tealish code may result a small gain. Reducing the variable usage help you ascetically if you are on the limit of budget cost. Variable assignment generates store, and usages generates load opcodes. So, you can remove the variables used one time.
1int a = get_int()
2int b = get_int()
3int c = get_int()
4
5int result = (a + b) + c
6
7# Dummy function
8func get_int() int:
9 return 2
10end
1int result = (get_int() + get_int()) + get_int()
2
3# Dummy function
4func get_int() int:
5 return 2
6end
Increasing the budget¶
The opcode budget of an application call is 700. Most TEAL Opcodes have a cost of 1
but some are much higher. For example b+ is 20 times more costly than b
If the transaction group has multiple application calls, the budget is pooled. The details are explained in the
Algorand Developer Documentation.
Similar to OpUp utility of PyTeal, you can increase the cost budget by adding another app call using inner transactions. Each app call adds an extra 700 to the budget.
increase_cost_budget creates and deletes an app with single transactions. This is the most portable and efficient way to achieve the goal.
1func increase_cost_budget():
2 inner_txn:
3 TypeEnum: Appl
4 OnCompletion: DeleteApplication
5 ApprovalProgram: "\x06\x81\x01"
6 ClearStateProgram: "\x06\x81\x01"
7 Fee: 0
8 end
9 return
10end
Testing & Debugging¶
After compiling the Tealish code into TEAL, you can use all the testing, and debugging tools that are compatible with TEAL. Using Sandbox node for testing and developing as explained on Algorand Developer Documentation is also an option.
Algojig¶
“ AlgoJig is a development and testing jig for Algorand. It allows developers to run transactions and write tests starting from a known Algorand ledger state. It is suitable for testing all kinds of transactions, including application calls and logic signatures.”
Counter Prize and Auction example contracts implemented by Tealish contains unit-tests and they use AlgoJig.
Example:
1 stxn = txn.sign(self.app_creator_sk)
2
3 block = self.ledger.eval_transactions(transactions=[stxn])
4 block_txns = block[b"txns"]
5
6 self.assertEqual(len(block_txns), 1)
7 txn = block_txns[0]
8
9 app_id = txn[b"apid"]
10 self.assertIsNotNone(app_id)
11
12 # check final state
13 final_global_state = self.ledger.get_global_state(
14 app_id=app_id,
15 )
16 self.assertDictEqual(
17 final_global_state,
18 {b"counter": 0},
19 )
20
21 # check delta
22 global_delta = txn[b"dt"][b"gd"]
23 self.assertDictEqual(
24 global_delta,
25 {b"counter": {b"at": 2}},
26 )