Repository: algorand/pyteal

Issue:
TEAL 5 support for PyTeal

Discussion:

Patch:
diff --git a/.travis.yml b/.travis.yml
index 3aea6df..9f2436e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,16 +17,16 @@ jobs:
       python: "3.7"
     - name: Python 3.8
       python: "3.8"
+    - name: Python 3.9
+      python: "3.9"
     - stage: Release
       name: PyPi release
-      python: "3.8"
+      python: "3.9"
       script: skip
       if: tag IS present AND type = push
       deploy:
         provider: pypi
         username: __token__
-        password:
-          secure: W0VZ1e3uo6+fVbJgrXsAdQc0WQCxuWVEX2DT4oOFhsX3GgTxi7I1phPmtZkl2gacuhfAQKN4XC04eZmgdYd3SrERWqae4/Fa9C/RvGwmhFCBpBYcr9c3CthUCIkgpRQVgTbmFzoWAX2/2YyzrWhjAv+CadrcP4KXcylOtdBEEYRZYz3LzhcNOJrDE/e9OQeziTiTUVs63iJniUvFDQxcbMfccpF1CGTsdTPqRllC7UfpE5CS/pVdHzyRVRmxw5Y3l53sqKi5uX4OWFwyIaqN37m0f4z+I6+L9oZ+FL8NCjTRfV8Lc9wT/PzSFBHcPhItyTg5/qbegm2TNx+zUeRWaRpG0HNHSHqF2QlaAvOcxufGb+QC/gvUYZfFEUXjhyCgb7W2QmB94Nwsm1S+35Vpjit7hJ9AXIaIfcJTa3KZR02gAuan9AS5mhDTR3TPZp4E4DWhC941/7zzACJOHoqU7u3lAd/0zuoIvUm0SmJfx1+wpSoxs4kf0c3LaitzCkXubj64PxtK3mJHVkJW9mRvmaGP7Akxd3BgW+3bZrbi/3/DBoWvth569xAoAFqI6bRdoritpDlBcVK8P1FzbwfZrTLNqyAAJ00StfHzttKYuSHB9TJdhdHhFbT2GLeWZ+8+dOqaw7D9jNyNyYAjbDKdCeo4y2aPclD1svrTs+jfHtw=
         on:
           tags: true
           branch: master
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ba90fdc..f9d09f3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,22 @@
+# 0.9.0
+
+## Added
+* Support for new TEAL 5 features:
+  * `AppParam` expressions ([#107](https://github.com/algorand/pyteal/pull/107), [#123](https://github.com/algorand/pyteal/pull/123))
+  * New `nonparticipation` transaction field ([#106](https://github.com/algorand/pyteal/pull/106))
+  * Inner transactions, zero-element `Seq` expressions, dynamic transaction array access ([#115](https://github.com/algorand/pyteal/pull/115))
+  * Logs, dynamic LogicSig argument indexes, single-element `NaryExpr`s, and creating `Bytes` from `bytes` and `bytearray` ([#117](https://github.com/algorand/pyteal/pull/117))
+  * Extract expressions ([#118](https://github.com/algorand/pyteal/pull/118))
+  * More efficient implementation of recursive subroutines in TEAL 5+ ([#114](https://github.com/algorand/pyteal/pull/114))
+* Add `WideRatio`, an expression which exposes `mulw` and `divmodw` ([#121](https://github.com/algorand/pyteal/pull/121), [#122](https://github.com/algorand/pyteal/pull/122))
+
+## Changed
+* **WARNING**: Due to code generation improvements, programs compiled with this version will likely
+  produce different TEAL code than previous versions, but their functionality will be the same. Be
+  aware that even small differences in generated TEAL code will change the address associated with
+  escrow LogicSig contracts.
+* Some unnecessary branch conditions have been removed ([#120](https://github.com/algorand/pyteal/pull/120))
+
 # 0.8.0
 
 ## Added
diff --git a/README.md b/README.md
index f2c7d1b..a3442d2 100644
--- a/README.md
+++ b/README.md
@@ -18,20 +18,25 @@ PyTeal provides high level, functional programming style abstractions over TEAL
 
 ### Install 
 
-PyTeal requires Python version >= 3.6
+PyTeal requires Python version >= 3.6.
 
-* `pip3 install pyteal`
+#### Recommended: Install from PyPi
 
-### Documentation
+Install the latest official release from PyPi:
 
-[PyTeal Docs](https://pyteal.readthedocs.io/)
+* `pip install pyteal`
+
+#### Install Latest Commit
+
+If needed, it's possible to install directly from the latest commit on master to use unreleased features:
 
-### Run Demo
+> **WARNING:** Unreleased code is experimental and may not be backwards compatible or function properly. Use extreme caution when installing PyTeal this way.
 
-In PyTeal root directory:
+* `pip install git+https://github.com/algorand/pyteal`
 
-* `jupyter notebook demo/Pyteal\ Demonstration.ipynb`
+### Documentation
 
+[PyTeal Docs](https://pyteal.readthedocs.io/)
 
 ### Development Setup
 
@@ -39,14 +44,14 @@ Setup venv (one time):
  * `python3 -m venv venv`
 
 Active venv:
- * `. venv/bin/activate.fish` (if your shell is fish)
  * `. venv/bin/activate` (if your shell is bash/zsh)
+ * `. venv/bin/activate.fish` (if your shell is fish)
 
 Pip install PyTeal in editable state
  * `pip install -e .`
 
 Install dependencies:
-* `pip3 install -r requirements.txt`
+* `pip install -r requirements.txt`
  
 Type checking using mypy:
 * `mypy pyteal`
diff --git a/docs/accessing_transaction_field.rst b/docs/accessing_transaction_field.rst
index a194100..db4a432 100644
--- a/docs/accessing_transaction_field.rst
+++ b/docs/accessing_transaction_field.rst
@@ -168,17 +168,19 @@ Global Parameters
 Information about the current state of the blockchain can be obtained using the following
 :any:`Global` expressions:
 
-======================================= ======================= ============================================================
-Operator                                Type                    Notes
-======================================= ======================= ============================================================
-:any:`Global.min_txn_fee()`             :code:`TealType.uint64` in microAlgos  
-:any:`Global.min_balance()`             :code:`TealType.uint64` in mircoAlgos
-:any:`Global.max_txn_life()`            :code:`TealType.uint64` number of rounds
-:any:`Global.zero_address()`            :code:`TealType.bytes`  32 byte address of all zero bytes
-:any:`Global.group_size()`              :code:`TealType.uint64` number of txns in this atomic transaction group, at least 1
-:any:`Global.logic_sig_version()`       :code:`TealType.uint64` the maximum supported TEAL version
-:any:`Global.round()`                   :code:`TealType.uint64` the current round number
-:any:`Global.latest_timestamp()`        :code:`TealType.uint64` the latest confirmed block UNIX timestamp
-:any:`Global.current_application_id()`  :code:`TealType.uint64` the ID of the current application executing
-:any:`Global.creator_address()`         :code:`TealType.bytes`  32 byte address of the creator of the current application
-======================================= ======================= ============================================================
+=========================================== ======================= ================ =============================================================
+Operator                                    Type                    Min TEAL Version Notes
+=========================================== ======================= ================ =============================================================
+:any:`Global.min_txn_fee()`                 :code:`TealType.uint64` 2                in microAlgos  
+:any:`Global.min_balance()`                 :code:`TealType.uint64` 2                in mircoAlgos
+:any:`Global.max_txn_life()`                :code:`TealType.uint64` 2                number of rounds
+:any:`Global.zero_address()`                :code:`TealType.bytes`  2                32 byte address of all zero bytes
+:any:`Global.group_size()`                  :code:`TealType.uint64` 2                number of txns in this atomic transaction group, at least 1
+:any:`Global.logic_sig_version()`           :code:`TealType.uint64` 2                the maximum supported TEAL version
+:any:`Global.round()`                       :code:`TealType.uint64` 2                the current round number
+:any:`Global.latest_timestamp()`            :code:`TealType.uint64` 2                the latest confirmed block UNIX timestamp
+:any:`Global.current_application_id()`      :code:`TealType.uint64` 2                the ID of the current application executing
+:any:`Global.creator_address()`             :code:`TealType.bytes`  3                32 byte address of the creator of the current application
+:any:`Global.current_application_address()` :code:`TealType.bytes`  5                32 byte address of the current application controlled account
+:any:`Global.group_id()`                    :code:`TealType.bytes`  5                32 byte ID of the current transaction group
+=========================================== ======================= ================ =============================================================
diff --git a/pyteal/ast/app.py b/pyteal/ast/app.py
index b59fd76..79ecd44 100644
--- a/pyteal/ast/app.py
+++ b/pyteal/ast/app.py
@@ -341,5 +341,18 @@ class AppParam:
             Op.app_params_get, TealType.bytes, immediate_args=["AppCreator"], args=[app]
         )
 
+    @classmethod
+    def address(cls, app: Expr) -> MaybeValue:
+        """Get the escrow address for the application.
+
+        Args:
+            app: An index into Txn.ForeignApps that correspond to the application to check.
+                Must evaluate to uint64.
+        """
+        require_type(app.type_of(), TealType.uint64)
+        return MaybeValue(
+            Op.app_params_get, TealType.bytes, immediate_args=["AppAddress"], args=[app]
+        )
+
 
 AppParam.__module__ = "pyteal"
diff --git a/pyteal/ast/global_.py b/pyteal/ast/global_.py
index 89117a5..b52a0f0 100644
--- a/pyteal/ast/global_.py
+++ b/pyteal/ast/global_.py
@@ -105,7 +105,7 @@ class Global(LeafExpr):
     def current_application_id(cls) -> "Global":
         """Get the ID of the current application executing.
 
-        Fails if no application is executing."""
+        Fails during Signature mode."""
         return cls(GlobalField.current_app_id)
 
     @classmethod
diff --git a/requirements.txt b/requirements.txt
index 16e7b86..a6f36fa 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,5 @@
 black==21.7b0
-ipython
-jupyter
-mypy
+mypy==0.910
 pytest
 pytest-timeout
 py-algorand-sdk
diff --git a/setup.py b/setup.py
index cf4bc0c..943d512 100644
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@ with open("README.md", "r") as fh:
 
 setuptools.setup(
     name="pyteal",
-    version="0.9.0.dev.1",
+    version="0.9.0",
     author="Algorand",
     author_email="pypiservice@algorand.com",
     description="Algorand Smart Contracts in Python",


Test patch:
diff --git a/pyteal/ast/app_test.py b/pyteal/ast/app_test.py
index 0cbbecd..95f6b4a 100644
--- a/pyteal/ast/app_test.py
+++ b/pyteal/ast/app_test.py
@@ -649,3 +649,31 @@ def test_app_param_creator_valid():
 def test_app_param_creator_invalid():
     with pytest.raises(TealTypeError):
         AppParam.creator(Txn.sender())
+
+
+def test_app_param_address_valid():
+    arg = Int(1)
+    expr = AppParam.address(arg)
+    assert expr.type_of() == TealType.none
+    assert expr.value().type_of() == TealType.bytes
+
+    expected = TealSimpleBlock(
+        [
+            TealOp(arg, Op.int, 1),
+            TealOp(expr, Op.app_params_get, "AppAddress"),
+            TealOp(None, Op.store, expr.slotOk),
+            TealOp(None, Op.store, expr.slotValue),
+        ]
+    )
+
+    actual, _ = expr.__teal__(teal5Options)
+    actual.addIncoming()
+    actual = TealBlock.NormalizeBlocks(actual)
+
+    with TealComponent.Context.ignoreExprEquality():
+        assert actual == expected
+
+
+def test_app_param_address_invalid():
+    with pytest.raises(TealTypeError):
+        AppParam.address(Txn.sender())