@goplausible/openclaw-algorand-plugin 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +112 -0
- package/index.ts +361 -0
- package/lib/mcp-servers.ts +14 -0
- package/lib/x402-fetch.ts +213 -0
- package/memory/algorand-plugin.md +82 -0
- package/openclaw.plugin.json +30 -0
- package/package.json +41 -0
- package/setup.ts +80 -0
- package/skills/algorand-development/SKILL.md +90 -0
- package/skills/algorand-development/references/build-smart-contracts-reference.md +79 -0
- package/skills/algorand-development/references/build-smart-contracts.md +52 -0
- package/skills/algorand-development/references/create-project-reference.md +86 -0
- package/skills/algorand-development/references/create-project.md +89 -0
- package/skills/algorand-development/references/implement-arc-standards-arc32-arc56.md +396 -0
- package/skills/algorand-development/references/implement-arc-standards-arc4.md +265 -0
- package/skills/algorand-development/references/implement-arc-standards.md +92 -0
- package/skills/algorand-development/references/search-algorand-examples-reference.md +119 -0
- package/skills/algorand-development/references/search-algorand-examples.md +89 -0
- package/skills/algorand-development/references/troubleshoot-errors-contract.md +373 -0
- package/skills/algorand-development/references/troubleshoot-errors-transaction.md +599 -0
- package/skills/algorand-development/references/troubleshoot-errors.md +105 -0
- package/skills/algorand-development/references/use-algokit-cli-reference.md +228 -0
- package/skills/algorand-development/references/use-algokit-cli.md +64 -0
- package/skills/algorand-interaction/SKILL.md +223 -0
- package/skills/algorand-interaction/references/algorand-mcp.md +743 -0
- package/skills/algorand-interaction/references/examples-algorand-mcp.md +647 -0
- package/skills/algorand-python/SKILL.md +95 -0
- package/skills/algorand-python/references/build-smart-contracts-decorators.md +413 -0
- package/skills/algorand-python/references/build-smart-contracts-reference.md +55 -0
- package/skills/algorand-python/references/build-smart-contracts-storage.md +452 -0
- package/skills/algorand-python/references/build-smart-contracts-transactions.md +445 -0
- package/skills/algorand-python/references/build-smart-contracts-types.md +438 -0
- package/skills/algorand-python/references/build-smart-contracts.md +82 -0
- package/skills/algorand-python/references/create-project-reference.md +55 -0
- package/skills/algorand-python/references/create-project.md +75 -0
- package/skills/algorand-python/references/implement-arc-standards-arc32-arc56.md +101 -0
- package/skills/algorand-python/references/implement-arc-standards-arc4.md +154 -0
- package/skills/algorand-python/references/implement-arc-standards.md +39 -0
- package/skills/algorand-python/references/troubleshoot-errors-contract.md +355 -0
- package/skills/algorand-python/references/troubleshoot-errors-transaction.md +430 -0
- package/skills/algorand-python/references/troubleshoot-errors.md +46 -0
- package/skills/algorand-python/references/use-algokit-utils-reference.md +350 -0
- package/skills/algorand-python/references/use-algokit-utils.md +76 -0
- package/skills/algorand-typescript/SKILL.md +131 -0
- package/skills/algorand-typescript/references/algorand-ts-migration-from-beta.md +448 -0
- package/skills/algorand-typescript/references/algorand-ts-migration-from-tealscript.md +487 -0
- package/skills/algorand-typescript/references/algorand-ts-migration.md +102 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-methods-and-abi.md +134 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-reference.md +58 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-storage.md +154 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-transactions.md +187 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-types-and-values.md +150 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax.md +84 -0
- package/skills/algorand-typescript/references/build-smart-contracts-reference.md +52 -0
- package/skills/algorand-typescript/references/build-smart-contracts.md +74 -0
- package/skills/algorand-typescript/references/call-smart-contracts-reference.md +237 -0
- package/skills/algorand-typescript/references/call-smart-contracts.md +183 -0
- package/skills/algorand-typescript/references/create-project-reference.md +53 -0
- package/skills/algorand-typescript/references/create-project.md +86 -0
- package/skills/algorand-typescript/references/deploy-react-frontend-examples.md +527 -0
- package/skills/algorand-typescript/references/deploy-react-frontend-reference.md +412 -0
- package/skills/algorand-typescript/references/deploy-react-frontend.md +239 -0
- package/skills/algorand-typescript/references/implement-arc-standards-arc32-arc56.md +73 -0
- package/skills/algorand-typescript/references/implement-arc-standards-arc4.md +126 -0
- package/skills/algorand-typescript/references/implement-arc-standards.md +44 -0
- package/skills/algorand-typescript/references/test-smart-contracts-examples.md +245 -0
- package/skills/algorand-typescript/references/test-smart-contracts-unit-tests.md +147 -0
- package/skills/algorand-typescript/references/test-smart-contracts.md +127 -0
- package/skills/algorand-typescript/references/troubleshoot-errors-contract.md +296 -0
- package/skills/algorand-typescript/references/troubleshoot-errors-transaction.md +438 -0
- package/skills/algorand-typescript/references/troubleshoot-errors.md +56 -0
- package/skills/algorand-typescript/references/use-algokit-utils-reference.md +342 -0
- package/skills/algorand-typescript/references/use-algokit-utils.md +74 -0
- package/skills/algorand-x402-python/SKILL.md +113 -0
- package/skills/algorand-x402-python/references/create-python-x402-client-examples.md +469 -0
- package/skills/algorand-x402-python/references/create-python-x402-client-reference.md +313 -0
- package/skills/algorand-x402-python/references/create-python-x402-client.md +207 -0
- package/skills/algorand-x402-python/references/create-python-x402-facilitator-examples.md +924 -0
- package/skills/algorand-x402-python/references/create-python-x402-facilitator-reference.md +629 -0
- package/skills/algorand-x402-python/references/create-python-x402-facilitator.md +408 -0
- package/skills/algorand-x402-python/references/create-python-x402-server-examples.md +703 -0
- package/skills/algorand-x402-python/references/create-python-x402-server-reference.md +303 -0
- package/skills/algorand-x402-python/references/create-python-x402-server.md +221 -0
- package/skills/algorand-x402-python/references/explain-algorand-x402-python-examples.md +605 -0
- package/skills/algorand-x402-python/references/explain-algorand-x402-python-reference.md +315 -0
- package/skills/algorand-x402-python/references/explain-algorand-x402-python.md +167 -0
- package/skills/algorand-x402-python/references/use-python-x402-core-avm-examples.md +554 -0
- package/skills/algorand-x402-python/references/use-python-x402-core-avm-reference.md +278 -0
- package/skills/algorand-x402-python/references/use-python-x402-core-avm.md +166 -0
- package/skills/algorand-x402-typescript/SKILL.md +129 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-client-examples.md +879 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-client-reference.md +371 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-client.md +236 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator-examples.md +875 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator-reference.md +461 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator.md +270 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs-examples.md +1181 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs-reference.md +360 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs.md +251 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall-examples.md +870 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall-reference.md +323 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall.md +281 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-server-examples.md +1135 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-server-reference.md +382 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-server.md +216 -0
- package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript-examples.md +616 -0
- package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript-reference.md +323 -0
- package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript.md +232 -0
- package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm-examples.md +1417 -0
- package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm-reference.md +504 -0
- package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm.md +158 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# ARC-32/56 Client Usage (Python)
|
|
2
|
+
|
|
3
|
+
This reference covers generating and using ARC-32/ARC-56 application specifications in Python.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Generating App Specs](#generating-app-specs)
|
|
8
|
+
- [Python Client Usage](#python-client-usage)
|
|
9
|
+
- [Factory and Deployment](#factory-and-deployment)
|
|
10
|
+
- [Calling Methods](#calling-methods)
|
|
11
|
+
- [State Access](#state-access)
|
|
12
|
+
- [Converting ARC-32 to ARC-56](#converting-arc-32-to-arc-56)
|
|
13
|
+
- [Events (ARC-28)](#events-arc-28)
|
|
14
|
+
|
|
15
|
+
## Generating App Specs
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Compile Python contract - generates both .arc32.json and .arc56.json
|
|
19
|
+
puyapy contracts/my_contract.py
|
|
20
|
+
|
|
21
|
+
# Or via AlgoKit
|
|
22
|
+
algokit project run build
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Output files:
|
|
26
|
+
- `MyContract.arc32.json` - Legacy app spec
|
|
27
|
+
- `MyContract.arc56.json` - Modern app spec
|
|
28
|
+
|
|
29
|
+
### Generate Typed Clients
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Python client from ARC-56
|
|
33
|
+
puyapy-clientgen MyContract.arc56.json
|
|
34
|
+
|
|
35
|
+
# Or with AlgoKit CLI
|
|
36
|
+
algokit generate client -o ./clients MyContract.arc56.json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Python Client Usage
|
|
40
|
+
|
|
41
|
+
### Factory and Deployment
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from algokit_utils import AlgorandClient
|
|
45
|
+
from artifacts.calculator_client import CalculatorFactory
|
|
46
|
+
|
|
47
|
+
algorand = AlgorandClient.default_localnet()
|
|
48
|
+
|
|
49
|
+
# Deploy new contract
|
|
50
|
+
factory = algorand.client.get_typed_app_factory(CalculatorFactory)
|
|
51
|
+
app_client, _ = factory.deploy(
|
|
52
|
+
on_schema_break="replace",
|
|
53
|
+
on_update="update",
|
|
54
|
+
)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Calling Methods
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
# Call methods with type hints
|
|
61
|
+
result = app_client.send.add(a=10, b=20)
|
|
62
|
+
print(result.return_value) # int: 30
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### State Access
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
# Read state
|
|
69
|
+
state = app_client.state.global_state.get_all()
|
|
70
|
+
print(state["counter"]) # Typed value
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Converting ARC-32 to ARC-56
|
|
74
|
+
|
|
75
|
+
AlgoKit Utils provides a conversion utility for migrating legacy ARC-32 specs:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from algokit_utils.applications.app_spec import arc32_to_arc56
|
|
79
|
+
|
|
80
|
+
arc56_spec = arc32_to_arc56(arc32_spec)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Events (ARC-28)
|
|
84
|
+
|
|
85
|
+
Events are emitted using `arc4.emit()` with typed event structs:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from algopy import arc4
|
|
89
|
+
|
|
90
|
+
class Transfer(arc4.Struct):
|
|
91
|
+
from_addr: arc4.Address
|
|
92
|
+
to_addr: arc4.Address
|
|
93
|
+
amount: arc4.UInt64
|
|
94
|
+
|
|
95
|
+
# In contract method
|
|
96
|
+
arc4.emit(Transfer(
|
|
97
|
+
from_addr=arc4.Address(sender),
|
|
98
|
+
to_addr=arc4.Address(receiver),
|
|
99
|
+
amount=arc4.UInt64(amount),
|
|
100
|
+
))
|
|
101
|
+
```
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# ARC-4 Implementation (Python)
|
|
2
|
+
|
|
3
|
+
This reference covers implementing and calling ARC-4 methods in Algorand Python.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Using ARC-4 Types in Contracts](#using-arc-4-types-in-contracts)
|
|
8
|
+
- [Calling ARC-4 Methods](#calling-arc-4-methods)
|
|
9
|
+
- [From Another Contract](#from-another-contract)
|
|
10
|
+
- [From Client (AlgoKit Utils)](#from-client-algokit-utils)
|
|
11
|
+
- [Common ARC-4 Patterns](#common-arc-4-patterns)
|
|
12
|
+
- [Structs](#structs)
|
|
13
|
+
- [Arrays](#arrays)
|
|
14
|
+
- [Bare Methods](#bare-methods)
|
|
15
|
+
|
|
16
|
+
## Using ARC-4 Types in Contracts
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
from algopy import ARC4Contract, arc4, Account, Asset, Application
|
|
20
|
+
|
|
21
|
+
class MyContract(ARC4Contract):
|
|
22
|
+
@arc4.abimethod
|
|
23
|
+
def demo_types(
|
|
24
|
+
self,
|
|
25
|
+
# Primitive types
|
|
26
|
+
amount: arc4.UInt64,
|
|
27
|
+
flag: arc4.Bool,
|
|
28
|
+
name: arc4.String,
|
|
29
|
+
|
|
30
|
+
# Reference types (automatically handled)
|
|
31
|
+
user: Account, # Passed as Account, encoded as uint8 index
|
|
32
|
+
token: Asset, # Passed as Asset, encoded as uint8 index
|
|
33
|
+
app: Application, # Passed as Application, encoded as uint8 index
|
|
34
|
+
|
|
35
|
+
# Complex types
|
|
36
|
+
data: arc4.DynamicBytes,
|
|
37
|
+
addr: arc4.Address,
|
|
38
|
+
) -> arc4.String:
|
|
39
|
+
return arc4.String("Success")
|
|
40
|
+
|
|
41
|
+
@arc4.abimethod
|
|
42
|
+
def with_transaction(
|
|
43
|
+
self,
|
|
44
|
+
payment: gtxn.PaymentTransaction, # Preceding payment in group
|
|
45
|
+
amount: arc4.UInt64,
|
|
46
|
+
) -> None:
|
|
47
|
+
assert payment.receiver == Global.current_application_address
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Calling ARC-4 Methods
|
|
51
|
+
|
|
52
|
+
### From Another Contract
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from algopy import arc4, Application
|
|
56
|
+
|
|
57
|
+
# Call method on another contract using method reference
|
|
58
|
+
result, txn = arc4.abi_call(
|
|
59
|
+
OtherContract.some_method,
|
|
60
|
+
arg1,
|
|
61
|
+
arg2,
|
|
62
|
+
app_id=other_app,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Or using method signature string
|
|
66
|
+
result, txn = arc4.abi_call[arc4.String](
|
|
67
|
+
"greet(string)string",
|
|
68
|
+
arc4.String("World"),
|
|
69
|
+
app_id=other_app,
|
|
70
|
+
)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### From Client (AlgoKit Utils)
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
result = client.send.add(a=10, b=20)
|
|
77
|
+
|
|
78
|
+
# Access return value
|
|
79
|
+
sum_value = result.return_value
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Getting Selector in Contract
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from algopy import arc4
|
|
86
|
+
|
|
87
|
+
# Get selector for a method by signature string
|
|
88
|
+
selector = arc4.arc4_signature("add(uint64,uint64)uint128")
|
|
89
|
+
|
|
90
|
+
# Or from a contract method reference
|
|
91
|
+
selector = arc4.arc4_signature(Calculator.add)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Common ARC-4 Patterns
|
|
95
|
+
|
|
96
|
+
### Structs
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from algopy import ARC4Contract, arc4
|
|
100
|
+
|
|
101
|
+
class UserInfo(arc4.Struct):
|
|
102
|
+
name: arc4.String
|
|
103
|
+
balance: arc4.UInt64
|
|
104
|
+
active: arc4.Bool
|
|
105
|
+
|
|
106
|
+
class MyContract(ARC4Contract):
|
|
107
|
+
@arc4.abimethod
|
|
108
|
+
def get_user(self, addr: arc4.Address) -> UserInfo:
|
|
109
|
+
return UserInfo(
|
|
110
|
+
name=arc4.String("Alice"),
|
|
111
|
+
balance=arc4.UInt64(1000),
|
|
112
|
+
active=arc4.Bool(True),
|
|
113
|
+
)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Arrays
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from algopy import ARC4Contract, arc4
|
|
120
|
+
from typing import Literal
|
|
121
|
+
|
|
122
|
+
# Fixed-size array
|
|
123
|
+
Balances = arc4.StaticArray[arc4.UInt64, Literal[10]]
|
|
124
|
+
|
|
125
|
+
# Dynamic array
|
|
126
|
+
Names = arc4.DynamicArray[arc4.String]
|
|
127
|
+
|
|
128
|
+
class MyContract(ARC4Contract):
|
|
129
|
+
@arc4.abimethod
|
|
130
|
+
def process_list(self, items: arc4.DynamicArray[arc4.UInt64]) -> arc4.UInt64:
|
|
131
|
+
total = arc4.UInt64(0)
|
|
132
|
+
for item in items:
|
|
133
|
+
total = arc4.UInt64(total.native + item.native)
|
|
134
|
+
return total
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Bare Methods
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from algopy import ARC4Contract, arc4
|
|
141
|
+
|
|
142
|
+
class MyContract(ARC4Contract):
|
|
143
|
+
@arc4.baremethod(create="require")
|
|
144
|
+
def create(self) -> None:
|
|
145
|
+
"""Called on app creation with no args."""
|
|
146
|
+
pass
|
|
147
|
+
|
|
148
|
+
@arc4.baremethod(allow_actions=["OptIn"])
|
|
149
|
+
def opt_in(self) -> None:
|
|
150
|
+
"""Called on OptIn with no args."""
|
|
151
|
+
pass
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Bare calls are identified by `NumAppArgs == 0`.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Implement ARC Standards (Python)
|
|
2
|
+
|
|
3
|
+
This reference covers implementing ARC standards in Algorand Python smart contracts and clients. ARC-4 defines the ABI for method calls and type encoding, while ARC-56 provides the modern application specification format for typed client generation.
|
|
4
|
+
|
|
5
|
+
## ARC-4 Contract Method Example
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from algopy import ARC4Contract, arc4
|
|
9
|
+
|
|
10
|
+
class Calculator(ARC4Contract):
|
|
11
|
+
@arc4.abimethod
|
|
12
|
+
def add(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt128:
|
|
13
|
+
return arc4.UInt128(a.native + b.native)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Using Typed Clients with ARC-56
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
from algokit_utils import AlgorandClient
|
|
20
|
+
from artifacts.calculator_client import CalculatorFactory
|
|
21
|
+
|
|
22
|
+
algorand = AlgorandClient.default_localnet()
|
|
23
|
+
|
|
24
|
+
# Deploy new contract
|
|
25
|
+
factory = algorand.client.get_typed_app_factory(CalculatorFactory)
|
|
26
|
+
app_client, _ = factory.deploy(
|
|
27
|
+
on_schema_break="replace",
|
|
28
|
+
on_update="update",
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Call methods with type hints
|
|
32
|
+
result = app_client.send.add(a=10, b=20)
|
|
33
|
+
print(result.return_value) # int: 30
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## References
|
|
37
|
+
|
|
38
|
+
- [Python ARC-4 Implementation](./implement-arc-standards-arc4.md) - ARC-4 types, contracts, and client calls
|
|
39
|
+
- [Python ARC-32/56 Client Usage](./implement-arc-standards-arc32-arc56.md) - App specs, typed clients, and state access
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
# Smart Contract Errors (Python)
|
|
2
|
+
|
|
3
|
+
Python-focused fixes for common Algorand smart contract errors.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Logic Eval Errors](#logic-eval-errors)
|
|
8
|
+
- [Assert Failed](#assert-failed)
|
|
9
|
+
- [Opcode Budget Exceeded](#opcode-budget-exceeded)
|
|
10
|
+
- [Invalid Program](#invalid-program)
|
|
11
|
+
- [Stack Underflow](#stack-underflow)
|
|
12
|
+
- [Byte/Int Type Mismatch](#byteint-type-mismatch)
|
|
13
|
+
- [ABI Errors](#abi-errors)
|
|
14
|
+
- [Method Not Found](#method-not-found)
|
|
15
|
+
- [ABI Encoding Error](#abi-encoding-error)
|
|
16
|
+
- [Return Value Decoding Error](#return-value-decoding-error)
|
|
17
|
+
- [State Errors](#state-errors)
|
|
18
|
+
- [Global State Full](#global-state-full)
|
|
19
|
+
- [Local State Not Opted In](#local-state-not-opted-in)
|
|
20
|
+
- [Box Not Found](#box-not-found)
|
|
21
|
+
- [Box MBR Not Met](#box-mbr-not-met)
|
|
22
|
+
- [Inner Transaction Errors](#inner-transaction-errors)
|
|
23
|
+
- [Debugging Tips](#debugging-tips)
|
|
24
|
+
|
|
25
|
+
## Logic Eval Errors
|
|
26
|
+
|
|
27
|
+
### Assert Failed
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
logic eval error: assert failed pc=123
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Cause:** An `assert` statement evaluated to false.
|
|
34
|
+
|
|
35
|
+
**Debug with source maps (LogicError):**
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from algokit_utils import LogicError
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
app_client.send.my_method(value=0)
|
|
42
|
+
except LogicError as e:
|
|
43
|
+
print(e) # Shows: assert failed at contracts/my_contract.py:45
|
|
44
|
+
print(e.pc) # Program counter: 123
|
|
45
|
+
print(e.line) # Source line number
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Common causes:**
|
|
49
|
+
- Input validation failed (e.g., `assert amount > 0`)
|
|
50
|
+
- Authorization check failed (e.g., `assert Txn.sender == self.owner`)
|
|
51
|
+
- State precondition not met (e.g., `assert self.is_initialized`)
|
|
52
|
+
|
|
53
|
+
**Fix:** Check the assertion condition and ensure inputs satisfy it.
|
|
54
|
+
|
|
55
|
+
### Opcode Budget Exceeded
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
logic eval error: dynamic cost budget exceeded
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Cause:** Contract exceeded the 700 opcode budget per app call.
|
|
62
|
+
|
|
63
|
+
**Budget limits:**
|
|
64
|
+
| Context | Budget |
|
|
65
|
+
|---------|--------|
|
|
66
|
+
| Single app call | 700 opcodes |
|
|
67
|
+
| Max pooled (16 app calls) | 11,200 opcodes |
|
|
68
|
+
| Logic signature | 20,000 opcodes |
|
|
69
|
+
|
|
70
|
+
**Fix - Pool budget with extra app calls:**
|
|
71
|
+
```python
|
|
72
|
+
# Add dummy app calls to increase budget
|
|
73
|
+
algorand.new_group()
|
|
74
|
+
.add_app_call_method_call(actual_call_params)
|
|
75
|
+
.add_app_call(AppCallParams(
|
|
76
|
+
sender=sender,
|
|
77
|
+
app_id=app_id,
|
|
78
|
+
on_complete=OnComplete.NoOp,
|
|
79
|
+
args=[b"noop"] # Dummy call for budget
|
|
80
|
+
))
|
|
81
|
+
.send()
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Optimize expensive operations:**
|
|
85
|
+
```python
|
|
86
|
+
# EXPENSIVE - iteration over large data
|
|
87
|
+
for i in range(100):
|
|
88
|
+
process(data[i])
|
|
89
|
+
|
|
90
|
+
# CHEAPER - batch operations or use Box storage
|
|
91
|
+
box_data = Box(Bytes, key=b"data")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Split across multiple calls:**
|
|
95
|
+
```python
|
|
96
|
+
# Instead of one large operation, split into phases
|
|
97
|
+
@arc4.abimethod
|
|
98
|
+
def process_phase1(self) -> None: ...
|
|
99
|
+
|
|
100
|
+
@arc4.abimethod
|
|
101
|
+
def process_phase2(self) -> None: ...
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Invalid Program
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
logic eval error: invalid program
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Cause:** The TEAL program is malformed or uses unsupported opcodes.
|
|
111
|
+
|
|
112
|
+
**Common causes:**
|
|
113
|
+
- Compiling for wrong AVM version
|
|
114
|
+
- Using opcodes not supported on target network
|
|
115
|
+
- Corrupted approval/clear program bytes
|
|
116
|
+
|
|
117
|
+
**Fix:** Ensure compilation targets the correct AVM version.
|
|
118
|
+
|
|
119
|
+
### Stack Underflow
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
logic eval error: stack underflow
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Cause:** Operation tried to pop from empty stack.
|
|
126
|
+
|
|
127
|
+
**In Algorand Python:** This usually indicates a bug in low-level operations. Check any `op.*` calls.
|
|
128
|
+
|
|
129
|
+
### Byte/Int Type Mismatch
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
logic eval error: assert failed: wanted type uint64 but got []byte
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Cause:** Wrong type passed to an operation.
|
|
136
|
+
|
|
137
|
+
**Common in Algorand Python:**
|
|
138
|
+
```python
|
|
139
|
+
# INCORRECT - String where UInt64 expected
|
|
140
|
+
assert payment.amount == "1000000"
|
|
141
|
+
|
|
142
|
+
# CORRECT - Use proper types
|
|
143
|
+
assert payment.amount == UInt64(1_000_000)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## ABI Errors
|
|
147
|
+
|
|
148
|
+
### Method Not Found
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
error: method "foo(uint64)void" not found
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Cause:** Calling a method that doesn't exist in the contract ABI.
|
|
155
|
+
|
|
156
|
+
**Fix:**
|
|
157
|
+
1. Regenerate the typed client after contract changes
|
|
158
|
+
2. Check the method signature matches exactly
|
|
159
|
+
3. Verify the contract was deployed with the latest code
|
|
160
|
+
|
|
161
|
+
### ABI Encoding Error
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
ABIEncodingError: value out of range for uint64
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Cause:** Value doesn't fit the ABI type.
|
|
168
|
+
|
|
169
|
+
**Examples:**
|
|
170
|
+
```python
|
|
171
|
+
# INCORRECT - Negative value for uint64
|
|
172
|
+
arc4.UInt64(-1)
|
|
173
|
+
|
|
174
|
+
# INCORRECT - Value too large
|
|
175
|
+
arc4.UInt8(256) # Max is 255
|
|
176
|
+
|
|
177
|
+
# CORRECT - Use appropriate type
|
|
178
|
+
arc4.UInt64(0)
|
|
179
|
+
arc4.UInt16(256)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Return Value Decoding Error
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
error: could not decode return value
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Cause:** Method returned unexpected data format.
|
|
189
|
+
|
|
190
|
+
**Common causes:**
|
|
191
|
+
- Contract didn't log the return value properly
|
|
192
|
+
- Wrong return type in client
|
|
193
|
+
- Transaction failed before return
|
|
194
|
+
|
|
195
|
+
**Fix:** Check contract method has correct return annotation.
|
|
196
|
+
|
|
197
|
+
## State Errors
|
|
198
|
+
|
|
199
|
+
### Global State Full
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
logic eval error: store global state: failed
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Cause:** Exceeded declared global state schema.
|
|
206
|
+
|
|
207
|
+
**Fix:** Increase schema in contract deployment:
|
|
208
|
+
```python
|
|
209
|
+
class MyContract(ARC4Contract):
|
|
210
|
+
# Declare more state slots in schema
|
|
211
|
+
@arc4.abimethod(create=True)
|
|
212
|
+
def create(self) -> None:
|
|
213
|
+
pass
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Local State Not Opted In
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
logic eval error: application APPID not opted in
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Cause:** Account hasn't opted into the application.
|
|
223
|
+
|
|
224
|
+
**Fix:** Opt in before accessing local state:
|
|
225
|
+
```python
|
|
226
|
+
algorand.send.app_call(AppCallParams(
|
|
227
|
+
sender=user_address,
|
|
228
|
+
app_id=app_id,
|
|
229
|
+
on_complete=OnComplete.OptIn,
|
|
230
|
+
))
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Box Not Found
|
|
234
|
+
|
|
235
|
+
```
|
|
236
|
+
logic eval error: box not found
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**Cause:** Accessing a box that doesn't exist.
|
|
240
|
+
|
|
241
|
+
**Fix:** Create box before access or check existence:
|
|
242
|
+
```python
|
|
243
|
+
# In contract - check if box exists
|
|
244
|
+
if self.my_box.exists:
|
|
245
|
+
value = self.my_box.value
|
|
246
|
+
else:
|
|
247
|
+
self.my_box.value = default_value
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Box MBR Not Met
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
logic eval error: box create with insufficient funds
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Cause:** App account lacks funds for box minimum balance requirement.
|
|
257
|
+
|
|
258
|
+
**MBR formula:** `2500 + (400 * (key_length + value_length))` microAlgos per box
|
|
259
|
+
|
|
260
|
+
**Fix:** Fund the app account:
|
|
261
|
+
```python
|
|
262
|
+
algorand.send.payment(PaymentParams(
|
|
263
|
+
sender=funder.address,
|
|
264
|
+
receiver=app_client.app_address,
|
|
265
|
+
amount=AlgoAmount(algo=1), # Cover box MBR
|
|
266
|
+
))
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Inner Transaction Errors
|
|
270
|
+
|
|
271
|
+
### Insufficient Balance for Inner Txn
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
logic eval error: insufficient balance
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Cause:** App account lacks funds for inner transaction amount.
|
|
278
|
+
|
|
279
|
+
**Fix:** Fund the app account before inner transactions:
|
|
280
|
+
```python
|
|
281
|
+
# Fund app before calling method with inner transactions
|
|
282
|
+
algorand.send.payment(PaymentParams(
|
|
283
|
+
sender=deployer.address,
|
|
284
|
+
receiver=app_client.app_address,
|
|
285
|
+
amount=AlgoAmount(algo=5),
|
|
286
|
+
))
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Inner Transaction Limit
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
logic eval error: too many inner transactions
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Cause:** Exceeded 256 inner transactions per group.
|
|
296
|
+
|
|
297
|
+
**Fix:** Split operations across multiple outer transactions.
|
|
298
|
+
|
|
299
|
+
### App Not Opted Into Asset
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
logic eval error: asset ASSET_ID not opted in
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Cause:** Contract account isn't opted into the asset.
|
|
306
|
+
|
|
307
|
+
**Fix:** Add opt-in method to contract:
|
|
308
|
+
```python
|
|
309
|
+
@arc4.abimethod
|
|
310
|
+
def opt_in_to_asset(self, asset: Asset) -> None:
|
|
311
|
+
itxn.AssetTransfer(
|
|
312
|
+
xfer_asset=asset,
|
|
313
|
+
asset_receiver=Global.current_application_address,
|
|
314
|
+
asset_amount=0,
|
|
315
|
+
fee=0
|
|
316
|
+
).submit()
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Debugging Tips
|
|
320
|
+
|
|
321
|
+
### Enable Debug Logging
|
|
322
|
+
|
|
323
|
+
```python
|
|
324
|
+
import logging
|
|
325
|
+
logging.getLogger("algokit").setLevel(logging.DEBUG)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Catch LogicError with Source Map
|
|
329
|
+
|
|
330
|
+
```python
|
|
331
|
+
from algokit_utils import LogicError
|
|
332
|
+
|
|
333
|
+
try:
|
|
334
|
+
app_client.send.my_method(value=0)
|
|
335
|
+
except LogicError as e:
|
|
336
|
+
print(e) # Full error with source mapping
|
|
337
|
+
print(e.pc) # Program counter
|
|
338
|
+
print(e.line) # Source line number
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Check Program Counter Location
|
|
342
|
+
|
|
343
|
+
When you see `pc=123`, use algokit to find the source:
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
algokit compile contracts/my_contract.py --output-sourcemap
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Then map the PC to source using the generated `.map` file.
|
|
350
|
+
|
|
351
|
+
## References
|
|
352
|
+
|
|
353
|
+
- [Debugging Smart Contracts](https://dev.algorand.co/concepts/smart-contracts/debugging/)
|
|
354
|
+
- [AVM Opcodes Reference](https://dev.algorand.co/reference/teal/opcodes/)
|
|
355
|
+
- [Error Handling in AlgoKit](https://dev.algorand.co/algokit/utils/typescript/debugging/)
|