Skip to content

Error Message for Box References where the application ID is unknown when creating app and box via inner txn #158

@atsoc1993

Description

@atsoc1993

As per @SilentRhetoric:

Would you kindly open a GH issue for this, please? At the very least, the error message is confusing and we should improve it

I am working with a contract where an inner txn creates a new application, and then subsequently a method is called within the same group to the newly created contract where a box has information written into it. The key for this box is known, but the application ID is not.

I was informed that currently the AVM does not (currently until the next consensus upgrade) support creating an application and simultaneously writing to its box (excluding exceptions where the application ID is predicted based on TC count).

The current error message when attempting to simultaneously create an application and write to a box via inner txns is:

algosdk.error.InvalidForeignIndexError: Box ref with appId 739088221 not in foreign-apps

Below is a contract and python code example to test creating an application via itxn and writing into a box in the created application. A FULL traceback is also available at the very bottom of this feature request for more accurate error description for this scenario.

Compile Contract:
algokit compile py contract.py --output-arc56

Generate Client:
algokitgen-py -a Test.arc56.json -o TestClient.py

Contract Code:

from algopy import ARC4Contract, subroutine, arc4, BoxMap, itxn, Global, Application, gtxn
from algopy.arc4 import abimethod, abi_call

class Test(ARC4Contract):
    def __init__(self) -> None:
        self.box_test = BoxMap(arc4.UInt64, arc4.UInt64, key_prefix='')

    @abimethod
    def create_application_via_inner_txn_then_write_to_box_in_created_app(self) -> None:
        current_app = Global.current_application_id

        app_created = itxn.ApplicationCall(
            approval_program=current_app.approval_program,
            clear_state_program=current_app.clear_state_program,
            global_num_uint=current_app.global_num_uint,
            global_num_bytes=current_app.global_num_bytes,
            local_num_uint=current_app.local_num_uint,
            local_num_bytes=current_app.local_num_bytes,
        ).submit().created_app

        self.call_write_box_method(created_app=app_created)

    @subroutine
    def call_write_box_method(self, created_app: Application) -> None:
        mbr_payment_itxn = itxn.Payment(
            receiver=created_app.address,
            amount=110_000
        )
        txn = abi_call(
            'write_to_box(pay)void',
            mbr_payment_itxn,
            app_id=created_app
        )
        
    @abimethod
    def write_to_box(self, mbr_payment: gtxn.PaymentTransaction) -> None:
        key = arc4.UInt64(0)
        value = arc4.UInt64(0)
        self.box_test[key] = value

Deploy and Call create_application_via_inner_txn_then_write_to_box_in_created_app method:

from TestClient import TestFactory
from algokit_utils import SigningAccount, PaymentParams, AlgoAmount, CommonAppCallParams, AlgorandClient
from algosdk.account import generate_account
import time

pk, address = generate_account()
print(pk, address)
signing_account = SigningAccount(private_key=pk, address=address)
signer = signing_account.signer
# Fund address while sleeping https://bank.testnet.algorand.network/
time.sleep(15)

algorand = AlgorandClient.testnet()
app_client, response = TestFactory(
    algorand=algorand,
    default_sender=address,
    default_signer=signer
).send.create.bare()

fund_app = algorand.send.payment(
    params=PaymentParams(
        sender=address,
        signer=signer,
        amount=AlgoAmount(algo=2),
        receiver=app_client.app_address,
        validity_window=1000,

    )
)
txn_response = app_client.send.create_application_via_inner_txn_then_write_to_box_in_created_app(
    params=CommonAppCallParams(
        max_fee=AlgoAmount(micro_algo=5000)
    ),
    send_params={
        'cover_app_call_inner_transaction_fees': True,
        'populate_app_call_resources': True
    }
)

# FAILS WHEN CALLING METHOD DUE TO INVALID BOX REFERENCE WHICH INCLUDES THE CREATED APP ID AS UNREFERENCED IN ERROR

Full Traceback:

Received error executing Atomic Transaction Composer, for more information enable the debug flag
Traceback (most recent call last):
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algosdk\box_reference.py", line 44, in translate_box_reference
    index = foreign_apps.index(ref_id) + 1
            ~~~~~~~~~~~~~~~~~~^^^^^^^^
ValueError: 739088221 is not in list

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\transactions\transaction_composer.py", line 1209, in send_atomic_transaction_composer
    atc = prepare_group_for_sending(
        atc,
    ...<3 lines>...
        additional_atc_context,
    )
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\transactions\transaction_composer.py", line 1142, in prepare_group_for_sending
    populate_group_resource(group, box, "box")
    ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\transactions\transaction_composer.py", line 1020, in populate_group_resource
    boxes.append(BoxReference.translate_box_reference(box_ref, app_txn.foreign_apps or [], app_txn.index))  # type: ignore[arg-type]
                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algosdk\box_reference.py", line 50, in translate_box_reference
    raise error.InvalidForeignIndexError(
        f"Box ref with appId {ref_id} not in foreign-apps"
    )
algosdk.error.InvalidForeignIndexError: Box ref with appId 739088221 not in foreign-apps
Traceback (most recent call last):
  File "c:\Users\atsoc\OneDrive\Desktop\GH Issue Contract\deploy_fund_call.py", line 30, in <module>
    txn_response = app_client.send.create_application_via_inner_txn_then_write_to_box_in_created_app(
        params=CommonAppCallParams(
    ...<5 lines>...
        }
    )
  File "c:\Users\atsoc\OneDrive\Desktop\GH Issue Contract\TestClient.py", line 166, in create_application_via_inner_txn_then_write_to_box_in_created_app
    response = self.app_client.send.call(algokit_utils.AppClientMethodCallParams(**{
        **dataclasses.asdict(params),
        "method": "create_application_via_inner_txn_then_write_to_box_in_created_app()void",
    }), send_params=send_params)
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\applications\app_client.py", line 1244, in call
    return self._client._handle_call_errors(
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        lambda: self._client._process_method_call_return(
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<2 lines>...
        )
        ^
    )
    ^
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\applications\app_client.py", line 1957, in _handle_call_errors
    raise self._expose_logic_error(e=e) from None
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\applications\app_client.py", line 1955, in _handle_call_errors
    return call()
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\applications\app_client.py", line 1245, in <lambda>
    lambda: self._client._process_method_call_return(
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        lambda: self._algorand.send.app_call_method_call(self._client.params.call(params), send_params),
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        self._app_spec.get_arc56_method(params.method),
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\applications\app_client.py", line 2097, in _process_method_call_return
    result_value = result()
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\applications\app_client.py", line 1246, in <lambda>
    lambda: self._algorand.send.app_call_method_call(self._client.params.call(params), send_params),
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\transactions\transaction_sender.py", line 1141, in app_call_method_call
    return self._send_app_call(lambda c: c.add_app_call_method_call)(params, send_params)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\transactions\transaction_sender.py", line 246, in send_app_call
    result = self._send(c, pre_log, post_log)(params, send_params)
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\transactions\transaction_sender.py", line 216, in send_transaction
    raw_result = composer.send(
        send_params,
    )
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\transactions\transaction_composer.py", line 1851, in send
    return send_atomic_transaction_composer(
        self._atc,
    ...<8 lines>...
        ),
    )
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\transactions\transaction_composer.py", line 1321, in send_atomic_transaction_composer
    raise e
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\transactions\transaction_composer.py", line 1209, in send_atomic_transaction_composer
    atc = prepare_group_for_sending(
        atc,
    ...<3 lines>...
        additional_atc_context,
    )
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\transactions\transaction_composer.py", line 1142, in prepare_group_for_sending
    populate_group_resource(group, box, "box")
    ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algokit_utils\transactions\transaction_composer.py", line 1020, in populate_group_resource
    boxes.append(BoxReference.translate_box_reference(box_ref, app_txn.foreign_apps or [], app_txn.index))  # type: ignore[arg-type]
                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\atsoc\AppData\Local\Programs\Python\Python313\Lib\site-packages\algosdk\box_reference.py", line 50, in translate_box_reference
    raise error.InvalidForeignIndexError(
        f"Box ref with appId {ref_id} not in foreign-apps"
    )
algosdk.error.InvalidForeignIndexError: Box ref with appId 739088221 not in foreign-apps

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions