Skip to content

Commit 82dbe2e

Browse files
michaeldiamantbarnjaminjasonpaulosCiottiGiorgioahangsu
authored
Add ABI support (#264)
* ABI Types (#154) * initial commit to be used for reference and comparison * Fmt * move abi to ast * make tuple return the deocded Tuple * rename collections, fixed some of the mypy issues * Fix mypy issues * remove Literal * add str method for abi type names * fix names * make imports nice * make imports nice * make collections generic * rm param spec * lie to mypy * make dynamic array work * [WIP] Make Add and Mul NaryExprs * ABI refactor * Implement decoding * Make arrays encode to a single value * Make types mutable * Proof of concept map implementation * Remove old comment * Update Uint16 limit check Co-authored-by: Giorgio Ciotti <[email protected]> * provide a method to know the type name (#176) * Refactor array implementation * Add ComputedType and fix bug in map * Add more int types and bool support * Add string method * Remove files for features that won't make it into this PR * Remove Array.map 😢 * Make decode more powerful * Uint bounds checking and tests * Remove random line * Bool tests and bugfixes * Allow uint and bool set to copy another type * Begin tuple and array tests, improve dynamic tuple encoding, and remove Array.forEach * Test indexTuple and fix bugs * Fix field shadowing * Finish tuple tests and type tests * Implement static and dynamic array tests * Finish testing abi types and fix tuple encoding bug * Add generic param to new instances of arrays * Address feedback * Fix tuple decoding issue * Fix uint64 decoding test * minor improvement to distinguish abi.Byte and abi.Uint8 (#194) * Add docstrings to abi.Type * Respond to feedback * Respond to feedback & fix bug * Fix indexTuple bug * Add docs for TealBlock methods * ABI Array docstrings and comments (#216) Co-authored-by: Jason Paulos <[email protected]> Co-authored-by: Giorgio Ciotti <[email protected]> Co-authored-by: Hang Su <[email protected]> * Merge with master and regenerate `__index__.pyi` (#224) * Fix build script invocation (#223) * Regen __init__.pyi * Reorder CI build steps to change source files before running tests (#225) Co-authored-by: Michael Diamant <[email protected]> * Merge #227 into feature/abi (#231) * Fix build script invocation (#223) * Bring #225 to master (#227) * Ignore tests generating TEAL file outputs used for expected comparisons (#228) * Fix typo in CONTRIBUTING.md (#229) Co-authored-by: Jason Paulos <[email protected]> * Make ABI types fully specified (#222) * Convert Type and Tuple to indexable types * Convert and combine uint types * Fix type and unit tests * Convert Bool * Fix Tuple getitem * Convert arrays and array tests * Fix tuple tests * [WIP] satisfy mypy * Refactor ABI types * Update docs, add Tuple4 and Tuple5, and change type_spec method name * No longer test on Python 3.6 and 3.7 * No longer test on Python 3.6 and 3.7 * Remove accidentally included file * Add another literal test case * Debugging through CI * blacken * Remove problematic test case * Minor test coverage improvements * Unit test to make sure type_spec_from_annotation always works on all types * Partially address feedback * Make uint8 != byte and use typing.Final in a few constructors * Undo custom set methods * Fix typo Co-authored-by: Michael Diamant <[email protected]> Co-authored-by: Michael Diamant <[email protected]> * Passing ABI type arguments to Subroutine (#263) - passing ABI variables into subroutine - subroutine type annotations with ABI types * ABI Method Return (#175) Encode ABI variable and concat with `RETURN_METHOD_SELECTOR` and log it. * Allow `ComputedType` to be passed to the `set` method on ABI types (#267) * update minor support for setting ComputedType * minor tweak * backwards for 3.8 on subscriptable type * attempt to test uint set * minor * cleanup * update arrays, tuple to test * tuple testing * update documents * resolving comments * py3.10 less go * python typing annotations * Merge branch 'master' into feature/abi (#284) * Move to pyteal as pt in ABI tests with concise prefix (#286) * ABI Strings (#278) * Move to pyteal as pt in #278 (#287) * Merge absolute imports into feature/abi (#288) * Remove temporary I252 ignore on pyteal.ast.abi (#290) * Fix abi import (#303) * Fix abi import * ignore flake8 * Feature/abi merge master again (#310) Following major changes: * Merge in Blackbox testing * replace `SubroutineDefinition. _arg_types_and_by_refs()` by `SubroutineDefinition._validate()` * add abi cases to `subroutine_test.py::test_validate()` * merge conflicts * merge again * wip * pass all tests after resolving conflicts * Add `set` on address and string, change array init to accept typespec (#289) * adding set on String and Address types * Add convenience `make` method for ABI types (#326) * Add make method for abi types * Respondn to feedback * ABI Type subroutine return (#256) * wtf * update * update to f-str * define void type * update instantiated computed type returnedType for ABI return in subroutine * minor * update stuffs to help infer type annotation of return ABI * minor * minor * minor * minor * minor * try my best to save stuffs * simplify decorator to single function * tear it down * minor * sheeeesh emacs * updates * minor, renaming something * new design, start over * updates * abi fn wrapper for now * minor * minor update on subroutine def * minor fixes * minor fixes * changes * more constraint on void ret * update comment examples * import from abi * update some error msg and comments * testcases partial * upgrade testscripts * Bundle optional refactorings to subroutine.py (#308) * Bundle optional refactorings to subroutine.py * Refactor to remove branching * storing local changes * pr review partly * pr review partly * update test script * Abi subroutine feature merge (#315) * resolve conflicts * lint * minor reconstruct * missing imports * missing requirements from bad merge * cooperate with typespec n var def change * update comments * some comments resolving? * trim * update some comments * bring testcase back * restriction on output kwarg name * stop ci! i am reformatting * simplify name constrain * resolving comments * Use deferred subroutine expression for ABI returns (#328) * Add subroutine deferred expr * Allow multiple deferred blocks * Remove error * flake8 * Make test more realistic * Add second test * clean up code and comments * remove deferred blocks function * Add coverage for multiple ops in block error * hack return from abi var * a hack * better returned type * simplify * add some compiler test * flake break no way * PR comment resolve partial * polishing Co-authored-by: Michael Diamant <[email protected]> Co-authored-by: Zeph Grunschlag <[email protected]> Co-authored-by: Zeph Grunschlag <[email protected]> Co-authored-by: Jason Paulos <[email protected]> * adding byte type hint to DyanamicArray parent class (#339) * adding byte type hint to DyanamicArray parent class * appease mypy * specify Byte in set method instead of T * Define level of support provided for ABIReturnSubroutine (#341) * Testing ABI Functionality via Graviton / Dry-runs + Txn Friendly Graviton Logic Sig Example (#322) # Blackbox Testing ABI Functionality This PR brings in dry-run testing of ABI types and subroutines. The space of ABI-Functionality that needs testing is large, and this PR doesn't purport to provide full coverage. However, the basic tools are provided to obtain greater coverage in the future. The following specific ABI use cases are tested: * abi_sum() which computes the sume of a DynamicArray * integers and complex integer number (Gassian integers) are built up from basic types and basic operations are validated * round-trip encoding and decoding of a number of ABI types # Testing Logic Sigs which interact with their Payment Transaction #249 introduced examples/signature/factorizer_game.py which includes a family of logic sigs that provide a payout that depends on the solution to an algebra puzzle. With a recent improvement to graviton we can now run blackbox tests on this logic sig family, and gain confidence in its correctness. See tests/integration/pure_logicsig_test.py for how this is done. * abi_roundtrip_test::test_abi_types_comprehensive() (#355) * adding sizeof util (#358) * adding size_of util * Reference Types (#361) * adding reference types to ABI types * Clearer Comment (#364) * Clearer Comment and link comment to issue #184 * Bug: Graviton's report no longer has last_rows (#365) * adding deref type to get the underlying value of the reference type (#372) * `ABI Router` implementation and test (#170) * init commit * minor * minor * rm decorator * update ABI router design, seems we are still working on previous design * minor * update condition parser here * skeleton for handler wrapping, need to tweak on subroutine to expose more message * module * use subroutine fn wrapper * update dummy method return class * unify ast construct way * minor * update notes for tasks and todos * update handler wrapping for bare app call * minor * update redirecting args to method registered * minor * minor * update router src * update program node * add questions in build prog * update executing method branch * minor * minor * minor * hide other methods, set MethodAppArgNumLimit, keyword args on exposed register func, skeleton for arg de-tuple * minor * update notes * update * add a default for no registered ast gen * update ast construction to conds * need some documentations * move abi-router in abi dir * minor * wtf * update * update to f-str * define void type * update instantiated computed type returnedType for ABI return in subroutine * minor * update stuffs to help infer type annotation of return ABI * minor * minor * minor * minor * minor * try my best to save stuffs * simplify decorator to single function * tear it down * minor * sheeeesh emacs * update with latest abi impl * minors * minor * updates * minor, renaming something * new design, start over * updates * abi fn wrapper for now * minor * minor update on subroutine def * minor fixes * minor fixes * changes * more constraint on void ret * update comment examples * import from abi * update some error msg and comments * testcases partial * upgrade testscripts * merging feature/abi to abi-router (#305) * merging feature/abi * missed one * make router use absolute imports * linter happy? * Export Router (#306) * Merge branch 'master' into feature/abi (#284) * Move to pyteal as pt in ABI tests with concise prefix (#286) * ABI Strings (#278) * Move to pyteal as pt in #278 (#287) * Merge absolute imports into feature/abi (#288) * Remove temporary I252 ignore on pyteal.ast.abi (#290) * Fix abi import (#303) * Fix abi import * ignore flake8 * move router to ast Co-authored-by: Michael Diamant <[email protected]> Co-authored-by: Jason Paulos <[email protected]> * fix spacing issue * Bundle optional refactorings to subroutine.py (#308) * Bundle optional refactorings to subroutine.py * Refactor to remove branching * storing local changes * pr review partly * pr review partly * update test script * Abi subroutine feature merge (#315) * resolve conflicts * lint * minor reconstruct * missing imports * missing requirements from bad merge * cooperate with typespec n var def change * update comments * some comments resolving? * trim * update some comments * bring testcase back * restriction on output kwarg name * stop ci! i am reformatting * squash merge abi subroutine atm, merge again after abi subroutine into feature/abi * conform to pep8, reconstructing * update json generator * simplify name constrain * resolving comments * Use deferred subroutine expression for ABI returns (#328) * Add subroutine deferred expr * Allow multiple deferred blocks * Remove error * flake8 * Make test more realistic * Add second test * clean up code and comments * remove deferred blocks function * Add coverage for multiple ops in block error * updating wrap handler * change how to de-tuple args * update checkbox * minor * bug fixes * Method sig for router (#340) * adding method_signature to ABIReturnSubroutine * minor, renaming * minor * simplify * compiler test adding... * documentation * start testcases * update router testcase * docstring tweak * update testcases * update testcases * formatting * branch cond testing * router contract test * subroutine branch wrapper bare call case tested * more testcases to barecall * minor, need to work on method call wrapper * half done on method call wrapper * update on abi method wrapper with return * detuple testcase * compiler test need to see csp * rm redundant type annotation * more error msg * renaming * renaming is_registrable -> is_abi_routable * reording imports, eliminate anti patterns * remove anti-pattern * section it out * non_empty_power_set -> power_set * add conflict detection to protect AST from overshadowing * error message * shrinked commits on pr review * add compile_program * fixup subroutine testcase * remove method signature specifying, directly infer from ABIReturnSubroutine * remove method sign field, directly infer from ABIReturnSubroutine * relaxation of bare app call arg num restriction * add barecall class, api change following * rename barecall to OnCompleteAction * remove outdated comments * start changing router api * eliminate contradiction for oc and creation * remove restriction on cond * new interface: add bare-calls on init, register method-call more fine-grained * documentation for new interface from last discussion * Refactor #170 to reduce visibility and mutation (#362) * Refactor to use partition * Designate _oc_under_call_config as private * hide wrap handler method * adding comment changes * pr review partly * partition into two methods * hide all these methods * arc4 compliant CallConfigs classmethod * arc4 compliant CallConfigs documentation * disclaimer comments * update new abi return hash prefix * review comments partly * OnCompleteActions -> BareCallActions * disclaimer change, rename CallConfigs -> MethodConfig * disclaimer move to docstring * better naming for naming prefix * new ast builder * review comments * An attempt to add decorator syntax to abi-router (#370) * an attempt to use decorator * no return, or we will have python-level issue? * minor fix * per pr comment on on-complete-action * eliminate potential issue * update call config testcase * add testcase for on complete action * per comments * Add a check in `method_signature` to disallow reference return types (#368) * new ast builder * adding check in method_signature to raise error if its attempted to be called on method with reference type as return value * use type spec instead of str * adding recursive type checking method and using it in subroutine method signature * Adding one more test case for extra nesting * appease the linter Co-authored-by: Hang Su <[email protected]> * add new compiler tests for router * fix one test for wrapping bare calls * comments fixing * simplified oc-action post_init check * naming variables * comments * comments * testcase for method config update * add router method only in clearstate prog * closeout -> clearstate * removing is_arc4_compliant * update add method handler and method interface * remove arc4_compliant * Add manual test for 15+ args in abi router (#375) Co-authored-by: Ben Guidarelli <[email protected]> Co-authored-by: Michael Diamant <[email protected]> Co-authored-by: Jason Paulos <[email protected]> Co-authored-by: Zeph Grunschlag <[email protected]> Co-authored-by: Zeph Grunschlag <[email protected]> * Adding method_spec to ABIReturnSubroutine (#380) * adding method_spec to ABIReturnSubroutine * Txn types (#376) * Add transaction abi types * Blackbox testing unifying abi-return-subroutine and subroutine input handling (#374) * unify subroutine case and abi-returning-subroutine * reconstruct code on argument prep and call * an example subroutine taking in abi arguments * update comment example and explanation * per pr comment * Changes to router clear state (#386) * define reference type spec (#383) * define reference type spec Co-authored-by: Jason Paulos <[email protected]> Co-authored-by: Zeph Grunschlag <[email protected]> * Rename decode parameters to abide by PEP8 conventions (#389) * More abi graviton tests (#391) * test_conditional_factorial() * Router return subroutine (#422) * Adding return value to add_method_call * Method call itxn (#387) * adding itxn method to call ABI method * __str__ formatting (#411) * standardize str formatting * Check transaction type arguments (#427) * Check transaction type arguments * Rename Transaction.set to be private * Check `Expr` length when converting to `abi.Address` (#432) * Fix on previous address length check (#433) * minor fix * minor * per Jason comment * minor, formatting * unit -> uint (#434) * Support declaring compatible PyTeal version in source code (#429) * Add semantic version dependency * Add `pragma` to enforce compatible compiler versions * Raise `TealInternalError` instead of `TealInputError` * Switch back to `pkg_resources` and convert PEP 440 to semantic version 2.0.0 * Fix linter errors * Make pep 440 converter private * Add `Pragma` expression * Refactor pragma functions from compiler to ast to avoid circular dependencies * Add `is_valid_compiler_version` check helper for the `Pragma` expression * Use `TealProgramError` instead of `TealInternalError` * Test underlying TEAL is unchanged * Refactor underlying pragma methods to parent directory * Inherit from `Expr` instead * Fix unclear docstring * Document init Document init * Add caret compiler version tests * Ignore unused fixture imports * Consistently use `start_index` and `end_index` (#436) * Consistently use start_ and end_index * format * allow passing router description to Contract constructor (#448) * allow passing router description to Contract constructor * Document new ABI features (#400) * Initial commit * Fix abi-docs tests (#402) * Fix abi-docs Sphinx warnings (#401) * Extend abi-docs with experimental design language (#403) * Add type fundamentals section * Add basic type usage and some docstrings for referenced methods * Finish documenting set and fix overloaded method docs * Add docstrings for get and __getitem__ * Add reference type docs * Add txn type examples * Fix errors * Make ComputedValue parameter type covariant * ComputedValue and subroutine sections * ...wasn't included in previous commit * Add bare app call and method registration examples * Add router e2e example and compilation explanation * Fix post-merge linter/test failures * Add calling documentation * Partially address feedback * Respond to feedback * Resolve TODOs * Add pragma references * didn't make it into the previous commit * Fix Bool.__module__ * Mention stack size limit * More pragma documentation * Address other feedback * Warn about reference type limits * **cannot** Co-authored-by: Michael Diamant <[email protected]> * Feature/abi merge master (#457) * Clarify minimum Python version management docs (#435) * Foreign prefix on App and Asset arrays (#440) * replacing foreignapps with applications * fix assets as well * Add Execute Method (#444) * adding execute method to allow omission of begin/submit for common use case * exec docstring * update testcase Co-authored-by: Hang Su <[email protected]> Co-authored-by: Michael Diamant <[email protected]> Co-authored-by: Ben Guidarelli <[email protected]> Co-authored-by: Hang Su <[email protected]> * `abi.Bool` improvements (#453) * abi.Bool improvements * Don't need Seq anymore * nor its import * No black, that was not a tuple * modify integreation tests * missed one * Missed a file * Rename pyteal/ast/abi/bool.py functions to follow PEP 8 conventions (#459) * Specify dependency versions (#464) * Rename pyteal/ast/abi/util.py functions to follow PEP 8 conventions (#460) * Rename pyteal/ast/abi/tuple.py functions to follow PEP 8 conventions (#461) * Fix typos in pyteal/ast/abi/util.py (#467) * Rename encoded_string to demarcate internal usage (#466) * Rename pyteal/ast/abi method parameters to follow PEP 8 conventions (#468) Co-authored-by: Ben Guidarelli <[email protected]> Co-authored-by: Jason Paulos <[email protected]> Co-authored-by: Giorgio Ciotti <[email protected]> Co-authored-by: Hang Su <[email protected]> Co-authored-by: Hang Su <[email protected]> Co-authored-by: Zeph Grunschlag <[email protected]> Co-authored-by: Zeph Grunschlag <[email protected]> Co-authored-by: Jacob Daitzman <[email protected]>
1 parent d51857b commit 82dbe2e

File tree

155 files changed

+27655
-601
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

155 files changed

+27655
-601
lines changed

.flake8

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ ignore =
1010

1111
per-file-ignores =
1212
pyteal/compiler/optimizer/__init__.py: F401
13+
examples/application/abi/algobank.py: F403, F405
1314
examples/application/asset.py: F403, F405
1415
examples/application/opup.py: F403, F405
1516
examples/application/security_token.py: F403, F405

.github/workflows/build.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- name: Install python dependencies
2424
run: make setup-development
2525
- name: Build and Test
26-
run: make build-and-test
26+
run: make lint-and-test
2727

2828
run-integration-tests:
2929
runs-on: ubuntu-20.04
@@ -63,8 +63,8 @@ jobs:
6363
run: make sandbox-dev-up
6464
- name: Install python dependencies
6565
run: make setup-development
66-
- name: Build, Unit Tests and Integration Tests
67-
run: make all-tests
66+
- name: Integration Tests Only
67+
run: make test-integration
6868
- name: Stop running images
6969
run: make sandbox-dev-stop
7070

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ celerybeat-schedule
102102
*.sage.py
103103

104104
# Environments
105+
_env
105106
.env
106107
.venv
107108
env/
@@ -138,3 +139,6 @@ dmypy.json
138139

139140
# mac OS
140141
.DS_Store
142+
143+
# asdf
144+
.tool-versions

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ black:
4040
flake8:
4141
flake8 $(ALLPY)
4242

43-
MYPY = pyteal scripts
43+
MYPY = pyteal scripts tests
4444
mypy:
4545
mypy --show-error-codes $(MYPY)
4646

@@ -54,9 +54,9 @@ test-unit:
5454
pytest -n $(NUM_PROCS) --durations=10 -sv pyteal tests/unit --ignore tests/unit/blackbox_test.py --ignore tests/unit/user_guide_test.py
5555
pytest -n 1 -sv tests/unit/blackbox_test.py tests/unit/user_guide_test.py
5656

57-
build-and-test: check-generate-init lint test-unit
57+
lint-and-test: check-generate-init lint test-unit
5858

59-
# ---- Integration Test (algod required) ---- #
59+
# ---- Integration Tests (algod required) ---- #
6060

6161
sandbox-dev-up:
6262
docker-compose up -d algod
@@ -69,7 +69,7 @@ integration-run:
6969

7070
test-integration: integration-run
7171

72-
all-tests: build-and-test test-integration
72+
all-tests: lint-and-test test-integration
7373

7474
# ---- Local Github Actions Simulation via `act` ---- #
7575
# assumes act is installed, e.g. via `brew install act`

docs/abi.rst

Lines changed: 917 additions & 0 deletions
Large diffs are not rendered by default.

docs/api.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,19 @@ PyTeal Package
2424
:annotation: = <pyteal.TxnObject object>
2525

2626
The most recently submitted inner transaction. This is an instance of :any:`TxnObject`.
27+
28+
If a transaction group was submitted most recently, then this will be the last transaction in that group.
29+
30+
.. data:: Gitxn
31+
:annotation: = <pyteal.InnerTxnGroup object>
32+
33+
The most recently submitted inner transaction group. This is an instance of :any:`InnerTxnGroup`.
34+
35+
If a single transaction was submitted most recently, then this will be a group of size 1.
36+
37+
.. automodule:: pyteal.abi
38+
:members:
39+
:undoc-members:
40+
:imported-members:
41+
:special-members: __getitem__
42+
:show-inheritance:

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ PyTeal **hasn't been security audited**. Use it at your own risk.
4545
versions
4646
compiler_optimization
4747
opup
48+
abi
4849

4950
.. toctree::
5051
:maxdepth: 3

docs/versions.rst

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.. _versions:
22

3-
TEAL Versions
3+
Versions
44
=============
55

66
Each version of PyTeal compiles contracts for a specific version of TEAL. Newer versions of TEAL
@@ -18,14 +18,34 @@ TEAL Version PyTeal Version
1818
6 >= 0.10.0
1919
============ ==============
2020

21+
.. _version pragmas:
22+
23+
Version Pragmas
24+
----------------
25+
26+
When writing a PyTeal smart contract, it's important to target a specific AVM version and to compile
27+
with a single PyTeal version. This will ensure your compiled program remains consistent and has the
28+
exact same behavior no matter when you compile it.
29+
30+
The :any:`pragma` function can be used to assert that the current PyTeal version matches a constraint
31+
of your choosing. This can help strengthen the dependency your source code has on the PyTeal package
32+
version you used when writing it.
33+
34+
If you are writing code for others to consume, or if your codebase has different PyTeal version
35+
dependencies in different places, the :any:`Pragma` expression can be used to apply a pragma
36+
constraint to only a section of the AST.
37+
38+
PyTeal v0.5.4 and Below
39+
-----------------------
40+
2141
In order to support TEAL v2, PyTeal v0.6.0 breaks backward compatibility with v0.5.4. PyTeal
2242
programs written for PyTeal version 0.5.4 and below will not compile properly and most likely will
2343
display an error of the form :code:`AttributeError: * object has no attribute 'teal'`.
2444

25-
**WARNING:** before updating PyTeal to a version with generates TEAL v2 contracts and fixing the
26-
programs to use the global function :any:`compileTeal` rather the class method :code:`.teal()`, make
27-
sure your program abides by the TEAL safety guidelines `<https://developer.algorand.org/docs/reference/teal/guidelines/>`_.
28-
Changing a v1 TEAL program to a v2 TEAL program without any code changes is insecure because v2
29-
TEAL programs allow rekeying. Specifically, you must add a check that the :code:`RekeyTo` property
30-
of any transaction is set to the zero address when updating an older PyTeal program from v0.5.4 and
31-
below.
45+
.. warning::
46+
If you are updating from a v1 TEAL program, make
47+
sure your program abides by the `TEAL safety guidelines <https://developer.algorand.org/docs/reference/teal/guidelines/>`_.
48+
Changing a v1 TEAL program to a v2 TEAL program without any code changes is insecure because v2
49+
TEAL programs allow rekeying. Specifically, you must add a check that the :code:`RekeyTo` property
50+
of any transaction is set to the zero address when updating an older PyTeal program from v0.5.4 and
51+
below.

examples/application/abi/__init__.py

Whitespace-only changes.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"name": "AlgoBank",
3+
"methods": [
4+
{
5+
"name": "deposit",
6+
"args": [
7+
{
8+
"type": "pay",
9+
"name": "payment"
10+
},
11+
{
12+
"type": "account",
13+
"name": "sender"
14+
}
15+
],
16+
"returns": {
17+
"type": "void"
18+
},
19+
"desc": "This method receives a payment from an account opted into this app and records it in their local state. The caller may opt into this app during this call."
20+
},
21+
{
22+
"name": "getBalance",
23+
"args": [
24+
{
25+
"type": "account",
26+
"name": "user"
27+
}
28+
],
29+
"returns": {
30+
"type": "uint64"
31+
},
32+
"desc": "Lookup the balance of a user held by this app."
33+
},
34+
{
35+
"name": "withdraw",
36+
"args": [
37+
{
38+
"type": "uint64",
39+
"name": "amount"
40+
},
41+
{
42+
"type": "account",
43+
"name": "recipient"
44+
}
45+
],
46+
"returns": {
47+
"type": "void"
48+
},
49+
"desc": "Withdraw an amount of Algos held by this app. The sender of this method call will be the source of the Algos, and the destination will be the `recipient` argument. This may or may not be the same as the sender's address. This method will fail if the amount of Algos requested to be withdrawn exceeds the amount of Algos held by this app for the sender. The Algos will be transferred to the recipient using an inner transaction whose fee is set to 0, meaning the caller's transaction must include a surplus fee to cover the inner transaction."
50+
}
51+
],
52+
"desc": null,
53+
"networks": {}
54+
}

examples/application/abi/algobank.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# This example is provided for informational purposes only and has not been audited for security.
2+
from pyteal import *
3+
import json
4+
5+
6+
@Subroutine(TealType.none)
7+
def assert_sender_is_creator() -> Expr:
8+
return Assert(Txn.sender() == Global.creator_address())
9+
10+
11+
# move any balance that the user has into the "lost" amount when they close out or clear state
12+
transfer_balance_to_lost = App.globalPut(
13+
Bytes("lost"),
14+
App.globalGet(Bytes("lost")) + App.localGet(Txn.sender(), Bytes("balance")),
15+
)
16+
17+
router = Router(
18+
name="AlgoBank",
19+
bare_calls=BareCallActions(
20+
# approve a creation no-op call
21+
no_op=OnCompleteAction(action=Approve(), call_config=CallConfig.CREATE),
22+
# approve opt-in calls during normal usage, and during creation as a convenience for the creator
23+
opt_in=OnCompleteAction(action=Approve(), call_config=CallConfig.ALL),
24+
# move any balance that the user has into the "lost" amount when they close out or clear state
25+
close_out=OnCompleteAction(
26+
action=transfer_balance_to_lost, call_config=CallConfig.CALL
27+
),
28+
clear_state=OnCompleteAction(
29+
action=transfer_balance_to_lost, call_config=CallConfig.CALL
30+
),
31+
# only the creator can update or delete the app
32+
update_application=OnCompleteAction(
33+
action=assert_sender_is_creator, call_config=CallConfig.CALL
34+
),
35+
delete_application=OnCompleteAction(
36+
action=assert_sender_is_creator, call_config=CallConfig.CALL
37+
),
38+
),
39+
)
40+
41+
42+
@router.method(no_op=CallConfig.CALL, opt_in=CallConfig.CALL)
43+
def deposit(payment: abi.PaymentTransaction, sender: abi.Account) -> Expr:
44+
"""This method receives a payment from an account opted into this app and records it in
45+
their local state.
46+
47+
The caller may opt into this app during this call.
48+
"""
49+
return Seq(
50+
Assert(payment.get().sender() == sender.address()),
51+
Assert(payment.get().receiver() == Global.current_application_address()),
52+
App.localPut(
53+
sender.address(),
54+
Bytes("balance"),
55+
App.localGet(sender.address(), Bytes("balance")) + payment.get().amount(),
56+
),
57+
)
58+
59+
60+
@router.method
61+
def getBalance(user: abi.Account, *, output: abi.Uint64) -> Expr:
62+
"""Lookup the balance of a user held by this app."""
63+
return output.set(App.localGet(user.address(), Bytes("balance")))
64+
65+
66+
@router.method
67+
def withdraw(amount: abi.Uint64, recipient: abi.Account) -> Expr:
68+
"""Withdraw an amount of Algos held by this app.
69+
70+
The sender of this method call will be the source of the Algos, and the destination will be
71+
the `recipient` argument. This may or may not be the same as the sender's address.
72+
73+
This method will fail if the amount of Algos requested to be withdrawn exceeds the amount of
74+
Algos held by this app for the sender.
75+
76+
The Algos will be transferred to the recipient using an inner transaction whose fee is set
77+
to 0, meaning the caller's transaction must include a surplus fee to cover the inner
78+
transaction.
79+
"""
80+
return Seq(
81+
# if amount is larger than App.localGet(Txn.sender(), Bytes("balance")), the subtraction
82+
# will underflow and fail this method call
83+
App.localPut(
84+
Txn.sender(),
85+
Bytes("balance"),
86+
App.localGet(Txn.sender(), Bytes("balance")) - amount.get(),
87+
),
88+
InnerTxnBuilder.Begin(),
89+
InnerTxnBuilder.SetFields(
90+
{
91+
TxnField.type_enum: TxnType.Payment,
92+
TxnField.receiver: recipient.address(),
93+
TxnField.amount: amount.get(),
94+
TxnField.fee: Int(0),
95+
}
96+
),
97+
InnerTxnBuilder.Submit(),
98+
)
99+
100+
101+
approval_program, clear_state_program, contract = router.compile_program(
102+
version=6, optimize=OptimizeOptions(scratch_slots=True)
103+
)
104+
105+
if __name__ == "__main__":
106+
with open("algobank_approval.teal", "w") as f:
107+
f.write(approval_program)
108+
109+
with open("algobank_clear_state.teal", "w") as f:
110+
f.write(clear_state_program)
111+
112+
with open("algobank.json", "w") as f:
113+
f.write(json.dumps(contract.dictify(), indent=4))

0 commit comments

Comments
 (0)