Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The TEAL opcode reference leaves behavior of some opcodes unspecified #282

Open
sskeirik opened this issue Jan 14, 2021 · 0 comments
Open

Comments

@sskeirik
Copy link

sskeirik commented Jan 14, 2021

Is your addition related to a problem? Please describe.

As far as I can tell, for several kinds of opcodes, the TEAL opcode reference (https://developer.algorand.org/docs/reference/teal/opcodes/) does not provide a complete description of their behavior. In particular, several descriptions of opcodes that deal with reading state do not seem to specify what happens when uninitialized state is read. See specific examples below.

Before continuing, I want to be clear that I understand there are two terms which have dual meanings: Accounts and ForeignApps.

  1. these both refer to application call transaction array-like fields
  2. these both refer to a separate VM-created array which is defined based on the txn field except:
    • index 0 refers to the account currently executing the application call or currently executing application, respectively.
    • index i with i != 1 refers to the i - 1th entry in the array-like field described in sense (1).

Note: In the descriptions below, I'm using definition (2). Thus, the minimum length of these arrays will always be 1.

From my reading, the return value is unspecified when:

  1. load - loading an uninitialized scratch space cell
  2. txn/gtxn - a transaction has type t and we read a field f of t where f was optional and unspecified
  3. txn/gtxn - a transaction has type t and we read a field f of a different transaction type t2
  4. txna/gtxna - a transaction has type t and an array-like field f and we read a value f[i] where index i >= len(f)
  5. gtxn/gtxna - we attempt to access a transaction at group index i where i >= GroupSize
  6. balance - we attempt to access the balance of the account at index i when i >= len(Accounts)
  7. arg_i/arg - we attempt to access the argument at index i when i >= len(Args)
  8. bytec_i/bytec - we attempt to access the byte constant in the byte block at index i when i >= len(bytecblock)
  9. intc_i/intc - we attempt to access the int constant in the int block at index i when i >= len(intcblock)
  10. app_local_put - we attempt to write to the application state of an account at index i when i >= len(Accounts)

The TEAL opcode reference on the opcode return value seems slightly unclear to me in the following cases. Typically, it says something like the value is zero if the key does not exist. I'm not sure if that explanation adequately covers all of the following cases. It would be helpful to extend the behavior description to specifically reference the following cases.

  1. app_local_get/app_local_get_ex - we attempt to access the application state of an account at index i when i >= len(Accounts)
  2. app_local_get/app_local_get_ex - the account at Accounts[i] has not not opted into the given application ID
  3. app_local_get_ex - we attempt to access the local application state of an application ID that is invalid
  4. app_global_get_ex - we attempt to access the global application state of the foreign application at index i when i >= len(ForeignApps)
  5. asset_holding_get - we attempt to access the asset holdings of an account at index i when i >= len(Accounts)
  6. asset_holding_get - we attempt to access the asset holdings of Accounts[i] that has not opted into using the given asset ID
  7. asset_params_get - we attempt to access the asset parameters of an asset at index i when i >= len(ForeignAssets)

Describe the solution you'd like

  1. For any case listed above which is indeed unspecified, I would like the TEAL opcode reference to define what happens.
  2. If my understanding is correct, I would like the TEAL opcode reference to always clarify the distinction between the two meanings of Accounts and ForeignApps.

Describe alternatives you've considered
Any unspecified behaviors could be documented as unspecified in the TEAL opcode reference.

Additional context
One might believe he/she could determine the type of a transaction at index i by doing (for example)

gtxn i CloseRemainderTo

since the CloseRemainderTo field only exists for payment transactions. However, upon inspection of the interpreter code, it appears that the txn family of opcodes will never panic; instead, it looks like they return a zero value in case a field is accessed that does not exist for the given transaction. This behavior has implications for transaction type checking. It means that either: we must check that the gtxn i f return value is non-zero (or possibly, depending on how transactions are validated) just directly check the return value of gtxn i Type. I think it may be worth updating the TEAL guidelines page (https://developer.algorand.org/docs/reference/teal/guidelines/) to replace:

- Type or TypeEnum can be checked to ensure something is a Payment or AssetXfer or another transaction type.

with something like (if the following is true):

- Checking the transaction Type or TypeEnum is the only way to ensure something is a Payment or AssetXfer or another transaction type.

If there are other ways to check that a transaction has the correct type, e.g., my suggestion about gtxn i f being non-zero, it would be good to add that to the list as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants
@winder @sskeirik and others