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

ARC-57: Application Action Routing #264

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions ARCs/arc-draft_action_routing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
arc: <to be assigned>
title: Application Action Routing
description: Standardized handling of OnCompletion and ApplicationID actions
author: Joe Polny (@joe-p)
discussions-to: <URL>
status: Draft
type: Standards Track
category: ARC
created: 2024-01-02
---

## Abstract
This ARC provides a standard way to handle an application call depending on the combination of the `OnCompletion` and `ApplicationID`.

## Motivation
Currently there is no way for someone to tell whether an app can be updated or deleted without doing a full static analysis on the TEAL.

## Specification

### TEAL
The TEAL for an application **MUST** start with the following lines:

```
txn ApplicationID
!
int 6
joe-p marked this conversation as resolved.
Show resolved Hide resolved
*
txn OnCompletion
+
switch call_NoOp call_OptIn call_CloseOut NOT_IMPLEMENTED call_UpdateApplication call_DeleteApplication create_NoOp create_OptIn NOT_IMPLEMENTED NOT_IMPLEMENTED NOT_IMPLEMENTED create_DeleteApplication
NOT_IMPLEMENTED:
err
```

For every action (combination of `ApplicationID === 0` and `OnCompletion`) there is a label that corresponds to that action. If that action is not implemented in the contract, its label should be replaced by a label that simply contains `err`. In the above TEAL, this is the `NOT_IMPLEMENTED` label.
Copy link
Contributor

@jannotti jannotti Jan 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An offchain parser has to check the destination of the label, that it contains err only? This is going to lead to extreme fragility in that we now have to worry about badly written parsers of TEAL code. If we change the disassembly output slightly (for example, add comments to a line, as we sometimes do), will they break? If not, they must be implementing a fully correct TEAL parser?

Since you're asking them to skip constant blocks, they have to handle all possible ways to write constants. There's base32 and base64 strings, for example.

This entry point is certainly one way to do things, and I know TealScript does. But nothing else does, and it doesn't seem best for immutable contracts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An offchain parser has to check the destination of the label, that it contains err only? This is going to lead to extreme fragility in that we now have to worry about badly written parsers of TEAL code. If we change the disassembly output slightly (for example, add comments to a line, as we sometimes do), will they break? If not, they must be implementing a fully correct TEAL parser?

As long as nothing is added before the opcodes then parses shouldn't have a problem if they check to ensure only the beginning matches. I can update the ARC to be more clear about this.

Since you're asking them to skip constant blocks, they have to handle all possible ways to write constants. There's base32 and base64 strings, for example.

I'm not sure I follow. If parsers ignore bytecblock and intcblock lines there aren't other types of constant blocks, are there? I know there are pseudo-ops for different encodings, but aren't those ultimately compiled to either pushbytes or put in the bytecblock?

This entry point is certainly one way to do things, and I know TealScript does. But nothing else does, and it doesn't seem best for immutable contracts.

A side benefit of this approach is that you can check what other "actions" are supported, but I don't think that's very important.

The alternative, as you suggested on discord would be asserts in the beginning. Parsers would check for txn OnComplete; pushint DeleteApplication; !=; assert or txn OnComplete; dup; pushint DeleteApplication; !=; assert; pushint UpdateApplication; != assert (I think checking for update is just as important as being able to check for delete). The main downside of this approach is extra ops/bytes in the program, but it's not a lot.


The label containing the `err` opcode **MUST** come right after the `switch` opcode.

The specific label names in the pre-compiled TEAL **MAY** be different, but it is **RECOMMENDED** to use the label names here for consistency across tooling.

The `switch` statement in a contract **SHOULD** only include labels until the last supported action is reached. For example, if an application only supports `NoOp` creations, the switch can simply be `switch create_NoOp`. All other actions will simply go to the next opcode, which **MUST** be `err` as specified above.

### Client Parsing

A client **MUST** parse the decompiled TEAL to ensure that the firt nine lines match the lines specified in the TEAL specification. `intcblock` and `bytecblock` opcodes **MUST** be ignored if they are the first or second opcodes executed.
joe-p marked this conversation as resolved.
Show resolved Hide resolved

The client **MUST** follow the label for a specific action. If that label does not exist in the `switch` opcode OR if it leads to the `err` label, then that action is known to not be supported by the TEAL.

## Rationale
Standardizing the initial opcodes of the TEAL program makes it easy for anyone to parse the TEAL, follow a label for a specific action, and and determine whether that action is supported or not.

## Backwards Compatibility
N/A

## Test Cases
N/A

## Reference Implementation
TODO: Client parsing example

## Security Considerations
If a client improperly implements parsing, they may mislead users about the mutability of the contract. It is imperative that `intcblock` and `bytecblock` are handled properly and the following opcodes are exactly as specificed in this ARC.

## Copyright
Copyright and related rights waived via <a href="https://creativecommons.org/publicdomain/zero/1.0/">CCO</a>.
Loading