From ef5f3382daae4b395354dfa56992e817f4fdbed7 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Tue, 14 Nov 2023 19:26:58 -0500 Subject: [PATCH 01/57] extended app description draft --- ARCs/arc-draft_extended_desc.md | 160 ++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 ARCs/arc-draft_extended_desc.md diff --git a/ARCs/arc-draft_extended_desc.md b/ARCs/arc-draft_extended_desc.md new file mode 100644 index 000000000..11e07f42b --- /dev/null +++ b/ARCs/arc-draft_extended_desc.md @@ -0,0 +1,160 @@ +--- +arc: +title: Extended App Description +description: Adds more information to the ARC4 JSON description +author: Joe Polny (@joe-p) +discussions-to: +status: Draft +type: Standards Track +category: ARC +created: 2023-11-14 +requires: 4 +--- + + +## Abstract +This ARC takes the existing JSON description of a contract as described in ARC4 and adds more fields for the purpose of client interaction + +## Motivation +The description provided by ARC4 is missing a lot of critical information that clients should know when interaction with an app. + +## Specification +```ts +/** Mapping of named structs to the ABI type of their fields */ +interface StructFields { + [name: string]: string | StructFields; +} + +/** Describes a single key in app storage */ +interface StorageKey { + /** The type of the key. Can be ABI type or named struct */ + keyType: string; + /** The type of the value. Can be ABI type or named struct */ + valueType: string; + /** The key itself, as a byte array */ + key: number[]; +} + +interface StorageMap { + /** The type of the key. Can be ABI type or named struct */ + keyType: string; + /** The type of the value. Can be ABI type or named struct */ + valueType: string; + /** The prefix of the map, as a string */ + prefix: string; +} + +interface Method { + /** The name of the method */ + name: string; + /** Optional, user-friendly description for the method */ + desc?: string; + /** The arguments of the method, in order */ + args: Array<{ + /** The type of the argument */ + type: string; + /** If the type is a struct, the name of the struct */ + struct?: string; + /** Optional, user-friendly name for the argument */ + name?: string; + /** Optional, user-friendly description for the argument */ + desc?: string; + }>; + /** Information about the method's return value */ + returns: { + /** The type of the return value, or "void" to indicate no return value. */ + type: string; + /** If the type is a struct, the name of the struct */ + struct?: string; + /** Optional, user-friendly description for the return value */ + desc?: string; + }; + /** an action is a combination of call/create and an OnComplete */ + actions: { + /** OnCompeltes this method allows when appID === 0 */ + create: ('NoOp' | 'OptIn' | 'DeleteApplication')[]; + /** OnCompeltes this method allows when appID !== 0 */ + call: ('NoOp' | 'OptIn' | 'CloseOut' | 'ClearState' | 'UpdateApplication' | 'DeleteApplication')[]; + }; + readonly: boolean; +} + +interface Contract { + /** A user-friendly name for the contract */ + name: string; + /** Optional, user-friendly description for the interface */ + desc?: string; + /** + * Optional object listing the contract instances across different networks + */ + networks?: { + /** + * The key is the base64 genesis hash of the network, and the value contains + * information about the deployed contract in the network indicated by the + * key + */ + [network: string]: { + /** The app ID of the deployed contract in this network */ + appID: number; + }; + }; + /** Named structs use by the application */ + structs: StructFields; + /** All of the methods that the contract implements */ + methods: Method[]; + state: { + schema: { + global: { + ints: number; + bytes: number; + }; + local: { + ints: number; + bytes: number; + }; + }; + /** Describes single key-value pairs in the application's state */ + keys: { + global: StorageKey[]; + local: StorageKey[]; + box: StorageKey[]; + }; + /** Describes key-value maps in the application's state */ + maps: { + global: StorageMap[]; + local: StorageMap[]; + box: StorageMap[]; + }; + }; +} +``` + +## Rationale +ARC32 essentially addresses the samr problem, but it requires the generation of two seperate JSON files (and ARC32 contains entirely redundant information). The goal of this ARC is to create one JSON schema that is backwards compatible with ARC4 clients. + +### State + +Describes all of the state that MAY exist in the app and how one should decode values. The schema provides the required schema when creating the app. + +### Named Structs + +It is common for high-level languages to support named structs, which gives names to the indexes of elements in an ABI tuple. The same structs should be useable on the client-side just as they are used in the contract. + +### Action + +This is one of the biggest deviation from ARC32, but provides a much simpler interface to describe and understand what any given method can do. + +## Backwards Compatibility +The JSON schema defined in this ARC should be compatible with all ARC4 clients, provided they don't do any strict schema checking for extraneous fields. + +## Test Cases +NA + +## Reference Implementation +TODO + +## Security Considerations +The type values used in methods are guranteed to be correct, because if they were not then the method would not be callable. For state, however, it is possible to have an incorrect type encoding defined. Any significant security concern from this possibility is not immediately evident, but it is worth considering. + +## Copyright +Copyright and related rights waived via CCO. From 6beb9f905f13e38782c0ddd8400ef439637e2f0f Mon Sep 17 00:00:00 2001 From: Joe Polny <50534337+joe-p@users.noreply.github.com> Date: Wed, 15 Nov 2023 06:09:45 -0500 Subject: [PATCH 02/57] apply rob's suggestions Co-authored-by: Rob Moore (MakerX) --- ARCs/arc-draft_extended_desc.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ARCs/arc-draft_extended_desc.md b/ARCs/arc-draft_extended_desc.md index 11e07f42b..444cbca48 100644 --- a/ARCs/arc-draft_extended_desc.md +++ b/ARCs/arc-draft_extended_desc.md @@ -16,7 +16,9 @@ requires: 4 This ARC takes the existing JSON description of a contract as described in ARC4 and adds more fields for the purpose of client interaction ## Motivation -The description provided by ARC4 is missing a lot of critical information that clients should know when interaction with an app. +The data provided by [ARC4](./arc-0004.md) is missing a lot of critical information that clients should know when interacting with an app. This means ARC4 is insufficient to generate type-safe clients that provide a superior developer experience. + +On the other hand, [ARC32](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0032.md) provides the vast majority of useful information that can be used to [generate typed clients](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients), but requires a separate JSON file on top of the ARC4 json file, which adds extra complexity and cognitive overhead. ## Specification ```ts @@ -130,7 +132,7 @@ interface Contract { ``` ## Rationale -ARC32 essentially addresses the samr problem, but it requires the generation of two seperate JSON files (and ARC32 contains entirely redundant information). The goal of this ARC is to create one JSON schema that is backwards compatible with ARC4 clients. +ARC32 essentially addresses the same problem, but it requires the generation of two separate JSON files and the ARC32 JSON file contains the ARC4 JSON file within it (redundant information). The goal of this ARC is to create one JSON schema that is backwards compatible with ARC4 clients, but contains the relevant information needed to automatically generate comprehensive client experiences. ### State From a18a968a16f3bb272c5da8d8e8d90f18eddb7ab8 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 15 Nov 2023 06:47:13 -0500 Subject: [PATCH 03/57] feedback based on rob's suggestions --- ARCs/arc-draft_extended_desc.md | 61 ++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/ARCs/arc-draft_extended_desc.md b/ARCs/arc-draft_extended_desc.md index 444cbca48..c20c60683 100644 --- a/ARCs/arc-draft_extended_desc.md +++ b/ARCs/arc-draft_extended_desc.md @@ -22,30 +22,41 @@ On the other hand, [ARC32](https://github.com/algorandfoundation/ARCs/blob/main/ ## Specification ```ts +type ABIType = string + +type StructName = string + +type AVMBytes = 'bytes' + /** Mapping of named structs to the ABI type of their fields */ interface StructFields { - [name: string]: string | StructFields; + [fieldName: string]: ABIType | StructFields; } /** Describes a single key in app storage */ interface StorageKey { - /** The type of the key. Can be ABI type or named struct */ - keyType: string; - /** The type of the value. Can be ABI type or named struct */ - valueType: string; - /** The key itself, as a byte array */ - key: number[]; + /** Description of what this storage key holds */ + desc?: string + /** The type of the key */ + keyType: ABIType | AVMBytes | StructName; + /** The type of the value */ + valueType: ABIType | AVMBytes | StructName; + /** The bytes of the key encoded as base64 */ + key: string; } interface StorageMap { - /** The type of the key. Can be ABI type or named struct */ - keyType: string; - /** The type of the value. Can be ABI type or named struct */ - valueType: string; - /** The prefix of the map, as a string */ + /** Description of what the key-value pairs in this mapping hold */ + desc?: string + /** The type of the keys in the map */ + keyType: ABIType | AVMBytes | StructName; + /** The type of the values in the map */ + valueType: ABIType | AVMBytes | StructName; + /** The prefix of the map, encoded as a utf-8 string */ prefix: string; } +/** Describes a method in the contract. This interface is an extension of the interface described in ARC4 */ interface Method { /** The name of the method */ name: string; @@ -54,9 +65,9 @@ interface Method { /** The arguments of the method, in order */ args: Array<{ /** The type of the argument */ - type: string; + type: ABIType; /** If the type is a struct, the name of the struct */ - struct?: string; + struct?: StructName; /** Optional, user-friendly name for the argument */ name?: string; /** Optional, user-friendly description for the argument */ @@ -65,9 +76,9 @@ interface Method { /** Information about the method's return value */ returns: { /** The type of the return value, or "void" to indicate no return value. */ - type: string; + type: ABIType; /** If the type is a struct, the name of the struct */ - struct?: string; + struct?: StructName; /** Optional, user-friendly description for the return value */ desc?: string; }; @@ -81,6 +92,7 @@ interface Method { readonly: boolean; } +/** Describes the entire contract. This interface is an extension of the interface described in ARC4 */ interface Contract { /** A user-friendly name for the contract */ name: string; @@ -101,10 +113,11 @@ interface Contract { }; }; /** Named structs use by the application */ - structs: StructFields; + structs: {[structName: StructName]: StructFields }; /** All of the methods that the contract implements */ methods: Method[]; state: { + /** Defines the values that should be used for GlobalNumUint, GlobalNumByteSlice, LocalNumUint, and LocalNumByteSlice when creating the application */ schema: { global: { ints: number; @@ -128,6 +141,20 @@ interface Contract { box: StorageMap[]; }; }; + /** Supported bare actions for the contract. An action is a combination of call/create and an OnComplete */ + bareActions: { + /** OnCompeltes this method allows when appID === 0 */ + create: ('NoOp' | 'OptIn' | 'DeleteApplication')[]; + /** OnCompeltes this method allows when appID !== 0 */ + call: ('NoOp' | 'OptIn' | 'CloseOut' | 'ClearState' | 'UpdateApplication' | 'DeleteApplication')[]; + }; + /** The uncompiled TEAL that may contain template variables. MUST be omitted if included as part of ARC23, but otherwise MUST be defined. */ + source?: { + /** The approval program */ + approval: string + /** The clear program */ + clear: string + }; } ``` From 126570991b7f91637e41d916b4bc89275cb38d87 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 15 Nov 2023 06:51:29 -0500 Subject: [PATCH 04/57] add comments to types --- ARCs/arc-draft_extended_desc.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ARCs/arc-draft_extended_desc.md b/ARCs/arc-draft_extended_desc.md index c20c60683..177e0414e 100644 --- a/ARCs/arc-draft_extended_desc.md +++ b/ARCs/arc-draft_extended_desc.md @@ -22,10 +22,13 @@ On the other hand, [ARC32](https://github.com/algorandfoundation/ARCs/blob/main/ ## Specification ```ts +/** An ABI-encoded type */ type ABIType = string +/** The name of a defined struct */ type StructName = string +/** Raw byteslice without the length prefixed that is specified in ARC4 */ type AVMBytes = 'bytes' /** Mapping of named structs to the ABI type of their fields */ From 1b19b761c6d0a5a35254ec46daa78ae7c000b16c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane?= Date: Thu, 16 Nov 2023 15:24:22 +0100 Subject: [PATCH 05/57] Assign number + fix linting --- ...{arc-draft_extended_desc.md => arc-0056.md} | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) rename ARCs/{arc-draft_extended_desc.md => arc-0056.md} (80%) diff --git a/ARCs/arc-draft_extended_desc.md b/ARCs/arc-0056.md similarity index 80% rename from ARCs/arc-draft_extended_desc.md rename to ARCs/arc-0056.md index 177e0414e..7b6c8fa96 100644 --- a/ARCs/arc-draft_extended_desc.md +++ b/ARCs/arc-0056.md @@ -1,9 +1,9 @@ --- -arc: +arc: 56 title: Extended App Description -description: Adds more information to the ARC4 JSON description +description: Adds information to the ABI JSON description author: Joe Polny (@joe-p) -discussions-to: +discussions-to: https://github.com/algorandfoundation/ARCs/issues/258 status: Draft type: Standards Track category: ARC @@ -13,12 +13,12 @@ requires: 4 ## Abstract -This ARC takes the existing JSON description of a contract as described in ARC4 and adds more fields for the purpose of client interaction +This ARC takes the existing JSON description of a contract as described in [ARC-4](./arc-0004.md) and adds more fields for the purpose of client interaction ## Motivation -The data provided by [ARC4](./arc-0004.md) is missing a lot of critical information that clients should know when interacting with an app. This means ARC4 is insufficient to generate type-safe clients that provide a superior developer experience. +The data provided by ARC-4 is missing a lot of critical information that clients should know when interacting with an app. This means ARC-4 is insufficient to generate type-safe clients that provide a superior developer experience. -On the other hand, [ARC32](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0032.md) provides the vast majority of useful information that can be used to [generate typed clients](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients), but requires a separate JSON file on top of the ARC4 json file, which adds extra complexity and cognitive overhead. +On the other hand, [ARC-32](./arc-0032.md) provides the vast majority of useful information that can be used to generate typed clients, but requires a separate JSON file on top of the ARC-4 json file, which adds extra complexity and cognitive overhead. ## Specification ```ts @@ -162,7 +162,7 @@ interface Contract { ``` ## Rationale -ARC32 essentially addresses the same problem, but it requires the generation of two separate JSON files and the ARC32 JSON file contains the ARC4 JSON file within it (redundant information). The goal of this ARC is to create one JSON schema that is backwards compatible with ARC4 clients, but contains the relevant information needed to automatically generate comprehensive client experiences. +ARC-32 essentially addresses the same problem, but it requires the generation of two separate JSON files and the ARC-32 JSON file contains the ARC-4 JSON file within it (redundant information). The goal of this ARC is to create one JSON schema that is backwards compatible with ARC-4 clients, but contains the relevant information needed to automatically generate comprehensive client experiences. ### State @@ -174,10 +174,10 @@ It is common for high-level languages to support named structs, which gives name ### Action -This is one of the biggest deviation from ARC32, but provides a much simpler interface to describe and understand what any given method can do. +This is one of the biggest deviation from ARC-32, but provides a much simpler interface to describe and understand what any given method can do. ## Backwards Compatibility -The JSON schema defined in this ARC should be compatible with all ARC4 clients, provided they don't do any strict schema checking for extraneous fields. +The JSON schema defined in this ARC should be compatible with all ARC-4 clients, provided they don't do any strict schema checking for extraneous fields. ## Test Cases NA From 45a4f6a3bf2ced534fb831e71d7c05e2ae6b9347 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Tue, 21 Nov 2023 08:46:55 -0500 Subject: [PATCH 06/57] add errors key --- ARCs/arc-0056.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 7b6c8fa96..9e1818f3a 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -151,6 +151,8 @@ interface Contract { /** OnCompeltes this method allows when appID !== 0 */ call: ('NoOp' | 'OptIn' | 'CloseOut' | 'ClearState' | 'UpdateApplication' | 'DeleteApplication')[]; }; + /** A mapping of program counters to human-readable error strings */ + errors: {[pc: number]: string}; /** The uncompiled TEAL that may contain template variables. MUST be omitted if included as part of ARC23, but otherwise MUST be defined. */ source?: { /** The approval program */ From 96bf57890f371c3633f7e32f01c09d2031170e43 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Fri, 29 Mar 2024 09:53:03 -0400 Subject: [PATCH 07/57] add defaultValue, fix typos --- ARCs/arc-0056.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 9e1818f3a..412b58de6 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -75,6 +75,8 @@ interface Method { name?: string; /** Optional, user-friendly description for the argument */ desc?: string; + /** The default value that clients should use. MUST be hex encoded bytes */ + defaultValue?: string }>; /** Information about the method's return value */ returns: { @@ -87,11 +89,12 @@ interface Method { }; /** an action is a combination of call/create and an OnComplete */ actions: { - /** OnCompeltes this method allows when appID === 0 */ + /** OnCompletes this method allows when appID === 0 */ create: ('NoOp' | 'OptIn' | 'DeleteApplication')[]; - /** OnCompeltes this method allows when appID !== 0 */ + /** OnCompletes this method allows when appID !== 0 */ call: ('NoOp' | 'OptIn' | 'CloseOut' | 'ClearState' | 'UpdateApplication' | 'DeleteApplication')[]; }; + /** If this method does not write anything to the ledger (ARC22) */ readonly: boolean; } @@ -146,14 +149,14 @@ interface Contract { }; /** Supported bare actions for the contract. An action is a combination of call/create and an OnComplete */ bareActions: { - /** OnCompeltes this method allows when appID === 0 */ + /** OnCompletes this method allows when appID === 0 */ create: ('NoOp' | 'OptIn' | 'DeleteApplication')[]; - /** OnCompeltes this method allows when appID !== 0 */ + /** OnCompletes this method allows when appID !== 0 */ call: ('NoOp' | 'OptIn' | 'CloseOut' | 'ClearState' | 'UpdateApplication' | 'DeleteApplication')[]; }; /** A mapping of program counters to human-readable error strings */ errors: {[pc: number]: string}; - /** The uncompiled TEAL that may contain template variables. MUST be omitted if included as part of ARC23, but otherwise MUST be defined. */ + /** The pre-compiled TEAL that may contain template variables. MUST be omitted if included as part of ARC23, but otherwise MUST be defined. */ source?: { /** The approval program */ approval: string @@ -188,7 +191,7 @@ NA TODO ## Security Considerations -The type values used in methods are guranteed to be correct, because if they were not then the method would not be callable. For state, however, it is possible to have an incorrect type encoding defined. Any significant security concern from this possibility is not immediately evident, but it is worth considering. +The type values used in methods **MUST** be correct, because if they were not then the method would not be callable. For state, however, it is possible to have an incorrect type encoding defined. Any significant security concern from this possibility is not immediately evident, but it is worth considering. ## Copyright Copyright and related rights waived via CCO. From 8c983a1631b62a40c82b229f5b98adeaef56da66 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Fri, 29 Mar 2024 10:00:30 -0400 Subject: [PATCH 08/57] ARC28, formatting --- ARCs/arc-0056.md | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 412b58de6..dd1a3a1d5 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -23,13 +23,13 @@ On the other hand, [ARC-32](./arc-0032.md) provides the vast majority of useful ## Specification ```ts /** An ABI-encoded type */ -type ABIType = string +type ABIType = string; /** The name of a defined struct */ -type StructName = string +type StructName = string; /** Raw byteslice without the length prefixed that is specified in ARC4 */ -type AVMBytes = 'bytes' +type AVMBytes = 'bytes'; /** Mapping of named structs to the ABI type of their fields */ interface StructFields { @@ -39,7 +39,7 @@ interface StructFields { /** Describes a single key in app storage */ interface StorageKey { /** Description of what this storage key holds */ - desc?: string + desc?: string; /** The type of the key */ keyType: ABIType | AVMBytes | StructName; /** The type of the value */ @@ -50,7 +50,7 @@ interface StorageKey { interface StorageMap { /** Description of what the key-value pairs in this mapping hold */ - desc?: string + desc?: string; /** The type of the keys in the map */ keyType: ABIType | AVMBytes | StructName; /** The type of the values in the map */ @@ -59,6 +59,24 @@ interface StorageMap { prefix: string; } +interface Event { + /** The name of the event */ + name: string; + /** Optional, user-friendly description for the event */ + desc?: string; + /** The arguments of the event, in order */ + args: Array<{ + /** The type of the argument */ + type: ABIType; + /** Optional, user-friendly name for the argument */ + name?: string; + /** Optional, user-friendly description for the argument */ + desc?: string; + /** If the type is a struct, the name of the struct */ + struct?: StructName; + }>; +} + /** Describes a method in the contract. This interface is an extension of the interface described in ARC4 */ interface Method { /** The name of the method */ @@ -76,7 +94,7 @@ interface Method { /** Optional, user-friendly description for the argument */ desc?: string; /** The default value that clients should use. MUST be hex encoded bytes */ - defaultValue?: string + defaultValue?: string; }>; /** Information about the method's return value */ returns: { @@ -96,6 +114,8 @@ interface Method { }; /** If this method does not write anything to the ledger (ARC22) */ readonly: boolean; + /** ARC28 events that MAY be emitted by this method */ + events: Array; } /** Describes the entire contract. This interface is an extension of the interface described in ARC4 */ @@ -119,7 +139,7 @@ interface Contract { }; }; /** Named structs use by the application */ - structs: {[structName: StructName]: StructFields }; + structs: { [structName: StructName]: StructFields }; /** All of the methods that the contract implements */ methods: Method[]; state: { @@ -155,17 +175,19 @@ interface Contract { call: ('NoOp' | 'OptIn' | 'CloseOut' | 'ClearState' | 'UpdateApplication' | 'DeleteApplication')[]; }; /** A mapping of program counters to human-readable error strings */ - errors: {[pc: number]: string}; + errors: { [pc: number]: string }; /** The pre-compiled TEAL that may contain template variables. MUST be omitted if included as part of ARC23, but otherwise MUST be defined. */ source?: { /** The approval program */ - approval: string + approval: string; /** The clear program */ - clear: string + clear: string; }; + /** ARC28 events that MAY be emitted by this contract */ + events: Array; } -``` +``` ## Rationale ARC-32 essentially addresses the same problem, but it requires the generation of two separate JSON files and the ARC-32 JSON file contains the ARC-4 JSON file within it (redundant information). The goal of this ARC is to create one JSON schema that is backwards compatible with ARC-4 clients, but contains the relevant information needed to automatically generate comprehensive client experiences. From a4c523e770bf5d4b265d19f179a15506646f2f11 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Fri, 29 Mar 2024 10:10:45 -0400 Subject: [PATCH 09/57] add sourceInfo --- ARCs/arc-0056.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index dd1a3a1d5..74b5cf51f 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -118,6 +118,15 @@ interface Method { events: Array; } +interface SourceInfo { + /** The line of pre-compiled TEAL */ + teal: number; + /** The program counter offset(s) that correspond to this line of TEAL */ + pc?: Array; + /** A human-readable string that describes the error when the program fails at this given line of TEAL */ + error?: string; +} + /** Describes the entire contract. This interface is an extension of the interface described in ARC4 */ interface Contract { /** A user-friendly name for the contract */ @@ -174,8 +183,8 @@ interface Contract { /** OnCompletes this method allows when appID !== 0 */ call: ('NoOp' | 'OptIn' | 'CloseOut' | 'ClearState' | 'UpdateApplication' | 'DeleteApplication')[]; }; - /** A mapping of program counters to human-readable error strings */ - errors: { [pc: number]: string }; + /** Information about the TEAL */ + sourceInfo: SourceInfo; /** The pre-compiled TEAL that may contain template variables. MUST be omitted if included as part of ARC23, but otherwise MUST be defined. */ source?: { /** The approval program */ From f6a62f024426a7eda96db9a5cff917ef2fdc32a0 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Fri, 29 Mar 2024 10:28:00 -0400 Subject: [PATCH 10/57] reorg spec --- ARCs/arc-0056.md | 242 +++++++++++++++++++++++++++-------------------- 1 file changed, 138 insertions(+), 104 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 74b5cf51f..bea52af9d 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -21,112 +21,11 @@ The data provided by ARC-4 is missing a lot of critical information that clients On the other hand, [ARC-32](./arc-0032.md) provides the vast majority of useful information that can be used to generate typed clients, but requires a separate JSON file on top of the ARC-4 json file, which adds extra complexity and cognitive overhead. ## Specification -```ts -/** An ABI-encoded type */ -type ABIType = string; - -/** The name of a defined struct */ -type StructName = string; - -/** Raw byteslice without the length prefixed that is specified in ARC4 */ -type AVMBytes = 'bytes'; - -/** Mapping of named structs to the ABI type of their fields */ -interface StructFields { - [fieldName: string]: ABIType | StructFields; -} - -/** Describes a single key in app storage */ -interface StorageKey { - /** Description of what this storage key holds */ - desc?: string; - /** The type of the key */ - keyType: ABIType | AVMBytes | StructName; - /** The type of the value */ - valueType: ABIType | AVMBytes | StructName; - /** The bytes of the key encoded as base64 */ - key: string; -} - -interface StorageMap { - /** Description of what the key-value pairs in this mapping hold */ - desc?: string; - /** The type of the keys in the map */ - keyType: ABIType | AVMBytes | StructName; - /** The type of the values in the map */ - valueType: ABIType | AVMBytes | StructName; - /** The prefix of the map, encoded as a utf-8 string */ - prefix: string; -} - -interface Event { - /** The name of the event */ - name: string; - /** Optional, user-friendly description for the event */ - desc?: string; - /** The arguments of the event, in order */ - args: Array<{ - /** The type of the argument */ - type: ABIType; - /** Optional, user-friendly name for the argument */ - name?: string; - /** Optional, user-friendly description for the argument */ - desc?: string; - /** If the type is a struct, the name of the struct */ - struct?: StructName; - }>; -} - -/** Describes a method in the contract. This interface is an extension of the interface described in ARC4 */ -interface Method { - /** The name of the method */ - name: string; - /** Optional, user-friendly description for the method */ - desc?: string; - /** The arguments of the method, in order */ - args: Array<{ - /** The type of the argument */ - type: ABIType; - /** If the type is a struct, the name of the struct */ - struct?: StructName; - /** Optional, user-friendly name for the argument */ - name?: string; - /** Optional, user-friendly description for the argument */ - desc?: string; - /** The default value that clients should use. MUST be hex encoded bytes */ - defaultValue?: string; - }>; - /** Information about the method's return value */ - returns: { - /** The type of the return value, or "void" to indicate no return value. */ - type: ABIType; - /** If the type is a struct, the name of the struct */ - struct?: StructName; - /** Optional, user-friendly description for the return value */ - desc?: string; - }; - /** an action is a combination of call/create and an OnComplete */ - actions: { - /** OnCompletes this method allows when appID === 0 */ - create: ('NoOp' | 'OptIn' | 'DeleteApplication')[]; - /** OnCompletes this method allows when appID !== 0 */ - call: ('NoOp' | 'OptIn' | 'CloseOut' | 'ClearState' | 'UpdateApplication' | 'DeleteApplication')[]; - }; - /** If this method does not write anything to the ledger (ARC22) */ - readonly: boolean; - /** ARC28 events that MAY be emitted by this method */ - events: Array; -} -interface SourceInfo { - /** The line of pre-compiled TEAL */ - teal: number; - /** The program counter offset(s) that correspond to this line of TEAL */ - pc?: Array; - /** A human-readable string that describes the error when the program fails at this given line of TEAL */ - error?: string; -} +### Contract Interface +Every application is described via the following interface which is an extension of the `Contract` interface described in [ARC4](./arc-0004.md). +```ts /** Describes the entire contract. This interface is an extension of the interface described in ARC4 */ interface Contract { /** A user-friendly name for the contract */ @@ -195,7 +94,142 @@ interface Contract { /** ARC28 events that MAY be emitted by this contract */ events: Array; } +``` + +### Method Interface + +Every method in the contract is described via a `Method` interface. This interface is an extension of the one defined in [ARC4](./arc-0004.md). + +```ts +/** Describes a method in the contract. This interface is an extension of the interface described in ARC4 */ +interface Method { + /** The name of the method */ + name: string; + /** Optional, user-friendly description for the method */ + desc?: string; + /** The arguments of the method, in order */ + args: Array<{ + /** The type of the argument */ + type: ABIType; + /** If the type is a struct, the name of the struct */ + struct?: StructName; + /** Optional, user-friendly name for the argument */ + name?: string; + /** Optional, user-friendly description for the argument */ + desc?: string; + /** The default value that clients should use. MUST be base64 encoded bytes */ + defaultValue?: string; + }>; + /** Information about the method's return value */ + returns: { + /** The type of the return value, or "void" to indicate no return value. */ + type: ABIType; + /** If the type is a struct, the name of the struct */ + struct?: StructName; + /** Optional, user-friendly description for the return value */ + desc?: string; + }; + /** an action is a combination of call/create and an OnComplete */ + actions: { + /** OnCompletes this method allows when appID === 0 */ + create: ('NoOp' | 'OptIn' | 'DeleteApplication')[]; + /** OnCompletes this method allows when appID !== 0 */ + call: ('NoOp' | 'OptIn' | 'CloseOut' | 'ClearState' | 'UpdateApplication' | 'DeleteApplication')[]; + }; + /** If this method does not write anything to the ledger (ARC22) */ + readonly: boolean; + /** ARC28 events that MAY be emitted by this method */ + events: Array; +} +``` + +### Event Interface + +[ARC28](./arc-0028.md) events are described using an extension of the original interface described in the ARC, with the addition of an optional struct field for arguments + +```ts +interface Event { + /** The name of the event */ + name: string; + /** Optional, user-friendly description for the event */ + desc?: string; + /** The arguments of the event, in order */ + args: Array<{ + /** The type of the argument */ + type: ABIType; + /** Optional, user-friendly name for the argument */ + name?: string; + /** Optional, user-friendly description for the argument */ + desc?: string; + /** If the type is a struct, the name of the struct */ + struct?: StructName; + }>; +} +``` + + +### Type Interfaces + +The types defined in [ARC4](./arc-0004.md) may not fully described the best way to use the ABI values as intended by the contract developers. These type interfaces are intended to supplement ABI types so clients can interact with the contract as intended. + +```ts +/** An ABI-encoded type */ +type ABIType = string; + +/** The name of a defined struct */ +type StructName = string; + +/** Raw byteslice without the length prefixed that is specified in ARC4 */ +type AVMBytes = 'bytes'; + +/** Mapping of named structs to the ABI type of their fields */ +interface StructFields { + [fieldName: string]: ABIType | StructFields; +} +``` +### Storage Interfaces + +These interfaces properly describe how app storage is access within the contract + +```ts +/** Describes a single key in app storage */ +interface StorageKey { + /** Description of what this storage key holds */ + desc?: string; + /** The type of the key */ + keyType: ABIType | AVMBytes | StructName; + /** The type of the value */ + valueType: ABIType | AVMBytes | StructName; + /** The bytes of the key encoded as base64 */ + key: string; +} + +interface StorageMap { + /** Description of what the key-value pairs in this mapping hold */ + desc?: string; + /** The type of the keys in the map */ + keyType: ABIType | AVMBytes | StructName; + /** The type of the values in the map */ + valueType: ABIType | AVMBytes | StructName; + /** The prefix of the map, encoded as a utf-8 string */ + prefix: string; +} +``` + +### SourceInfo Interface + +This interface gives clients more information about the contract's source code. + +```ts +interface SourceInfo { + /** The line of pre-compiled TEAL */ + teal: number; + /** The program counter offset(s) that correspond to this line of TEAL */ + pc?: Array; + /** A human-readable string that describes the error when the program fails at this given line of TEAL */ + error?: string; +} ``` ## Rationale ARC-32 essentially addresses the same problem, but it requires the generation of two separate JSON files and the ARC-32 JSON file contains the ARC-4 JSON file within it (redundant information). The goal of this ARC is to create one JSON schema that is backwards compatible with ARC-4 clients, but contains the relevant information needed to automatically generate comprehensive client experiences. From 358a65b5be961e538090cae74ee70b8474d215f1 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Fri, 29 Mar 2024 10:36:59 -0400 Subject: [PATCH 11/57] add arcs key --- ARCs/arc-0056.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index bea52af9d..46c7fa467 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -28,6 +28,8 @@ Every application is described via the following interface which is an extension ```ts /** Describes the entire contract. This interface is an extension of the interface described in ARC4 */ interface Contract { + /** The ARCs used and/or supported by this contract */ + arcs: number[], /** A user-friendly name for the contract */ name: string; /** Optional, user-friendly description for the interface */ From d9046e17e38fc7d0ffa8baec6f02620104110d20 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Fri, 29 Mar 2024 10:47:22 -0400 Subject: [PATCH 12/57] network names --- ARCs/arc-0056.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 46c7fa467..1c251c4cd 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -41,7 +41,8 @@ interface Contract { /** * The key is the base64 genesis hash of the network, and the value contains * information about the deployed contract in the network indicated by the - * key + * key. A key containing the human-readable name of the network MAY be + * included, but the corresponding genesis hash key MUST also be defined */ [network: string]: { /** The app ID of the deployed contract in this network */ From 9a5e445a9c735eab44f7c9677320d6b503f7bd50 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Fri, 29 Mar 2024 10:55:17 -0400 Subject: [PATCH 13/57] fix arc format --- ARCs/arc-0056.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 1c251c4cd..7560e485c 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -23,10 +23,10 @@ On the other hand, [ARC-32](./arc-0032.md) provides the vast majority of useful ## Specification ### Contract Interface -Every application is described via the following interface which is an extension of the `Contract` interface described in [ARC4](./arc-0004.md). +Every application is described via the following interface which is an extension of the `Contract` interface described in [ARC-4](./arc-0004.md). ```ts -/** Describes the entire contract. This interface is an extension of the interface described in ARC4 */ +/** Describes the entire contract. This interface is an extension of the interface described in ARC-4 */ interface Contract { /** The ARCs used and/or supported by this contract */ arcs: number[], @@ -94,17 +94,17 @@ interface Contract { /** The clear program */ clear: string; }; - /** ARC28 events that MAY be emitted by this contract */ + /** ARC-28 events that MAY be emitted by this contract */ events: Array; } ``` ### Method Interface -Every method in the contract is described via a `Method` interface. This interface is an extension of the one defined in [ARC4](./arc-0004.md). +Every method in the contract is described via a `Method` interface. This interface is an extension of the one defined in [ARC-4](./arc-0004.md). ```ts -/** Describes a method in the contract. This interface is an extension of the interface described in ARC4 */ +/** Describes a method in the contract. This interface is an extension of the interface described in ARC-4 */ interface Method { /** The name of the method */ name: string; @@ -139,16 +139,16 @@ interface Method { /** OnCompletes this method allows when appID !== 0 */ call: ('NoOp' | 'OptIn' | 'CloseOut' | 'ClearState' | 'UpdateApplication' | 'DeleteApplication')[]; }; - /** If this method does not write anything to the ledger (ARC22) */ + /** If this method does not write anything to the ledger (ARC-22) */ readonly: boolean; - /** ARC28 events that MAY be emitted by this method */ + /** ARC-28 events that MAY be emitted by this method */ events: Array; } ``` ### Event Interface -[ARC28](./arc-0028.md) events are described using an extension of the original interface described in the ARC, with the addition of an optional struct field for arguments +[ARC-28](./arc-0028.md) events are described using an extension of the original interface described in the ARC, with the addition of an optional struct field for arguments ```ts interface Event { @@ -173,7 +173,7 @@ interface Event { ### Type Interfaces -The types defined in [ARC4](./arc-0004.md) may not fully described the best way to use the ABI values as intended by the contract developers. These type interfaces are intended to supplement ABI types so clients can interact with the contract as intended. +The types defined in [ARC-4](./arc-0004.md) may not fully described the best way to use the ABI values as intended by the contract developers. These type interfaces are intended to supplement ABI types so clients can interact with the contract as intended. ```ts /** An ABI-encoded type */ @@ -182,7 +182,7 @@ type ABIType = string; /** The name of a defined struct */ type StructName = string; -/** Raw byteslice without the length prefixed that is specified in ARC4 */ +/** Raw byteslice without the length prefixed that is specified in ARC-4 */ type AVMBytes = 'bytes'; /** Mapping of named structs to the ABI type of their fields */ From ef47b89ce2178aca6986c0d8fbbd5261fb246ed0 Mon Sep 17 00:00:00 2001 From: Joe Polny <50534337+joe-p@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:26:37 -0400 Subject: [PATCH 14/57] require ARC28 Co-authored-by: Cosimo Bassi <65770425+cusma@users.noreply.github.com> --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 7560e485c..9e05bffb0 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -8,7 +8,7 @@ status: Draft type: Standards Track category: ARC created: 2023-11-14 -requires: 4 +requires: 4, 28 --- From 8e3499b2b0e52ae78c47901d9f9fa696b53fdb8e Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 24 Apr 2024 13:40:11 -0400 Subject: [PATCH 15/57] add Method.recommendations, Contract.templateVariables --- ARCs/arc-0056.md | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 9e05bffb0..1aa290af5 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -8,7 +8,7 @@ status: Draft type: Standards Track category: ARC created: 2023-11-14 -requires: 4, 28 +requires: 4, 28, 22 --- @@ -95,7 +95,14 @@ interface Contract { clear: string; }; /** ARC-28 events that MAY be emitted by this contract */ - events: Array; + events?: Array; + /** Template Variables */ + templateVariables?: { + /** The name of the template variable as it appears in the TEAL */ + name: string; + /** The type of the value expected in the template variable */ + type: ABIType | AVMBytes | StructName; + }[]; } ``` @@ -142,7 +149,29 @@ interface Method { /** If this method does not write anything to the ledger (ARC-22) */ readonly: boolean; /** ARC-28 events that MAY be emitted by this method */ - events: Array; + events?: Array; + /** Information that clients can use when calling the method */ + recommendations?: { + /** The number of inner transactions the caller should cover the fees for */ + innerTransactionCount?: number; + /** Recommended box references to include */ + boxes?: { + /** The app ID for the box */ + app: number; + /** The base64 encoded box key */ + key: string; + /** The number of bytes being read from the box */ + readBytes: number; + /** The number of bytes being written to the box */ + writeBytes: number; + }; + /** Recommended foreign accounts */ + accounts?: string[]; + /** Recommended foreign apps */ + apps?: number[]; + /** Recommended foreign assets */ + assets?: number[]; + }; } ``` From b02c3c1899664fbe70ff9c622a63df8a90b4ca38 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 24 Apr 2024 13:45:17 -0400 Subject: [PATCH 16/57] add template vars to spec --- ARCs/arc-0056.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 1aa290af5..591fa330a 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -263,6 +263,34 @@ interface SourceInfo { error?: string; } ``` + +### Template Variables + +Template variables are variables in the TEAL that should be substitued prior to compilation. Template variables **MUST** be an argument to either `pushints` or `pusbytes`. Using these opcodes is important to ensure that the program does not add them to the constant blocks. + +#### Examples +##### Valid +``` +pushints TMPL_FOO +pushbytes TMPL_BAR +``` + +#### Invalid + +Template variables MUST use pushints or pushbytes + +``` +int TMPL_FOO +byte TMPL_BYTE +``` + +Template variables MUST be the entire argument + +``` +pushints 123TMPL_FOO +pusbytes 0xdeadTMPL_BAR +``` + ## Rationale ARC-32 essentially addresses the same problem, but it requires the generation of two separate JSON files and the ARC-32 JSON file contains the ARC-4 JSON file within it (redundant information). The goal of this ARC is to create one JSON schema that is backwards compatible with ARC-4 clients, but contains the relevant information needed to automatically generate comprehensive client experiences. From 2a5eb6f7c189e23c32080a1a2bd5c38c8b16a5a9 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 24 Apr 2024 13:45:47 -0400 Subject: [PATCH 17/57] requires order --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 591fa330a..94b84b2e7 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -8,7 +8,7 @@ status: Draft type: Standards Track category: ARC created: 2023-11-14 -requires: 4, 28, 22 +requires: 4, 22, 28 --- From cebfc7d25b63a3fe345fab3f97de5b19356fe17d Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Fri, 26 Apr 2024 08:28:31 -0400 Subject: [PATCH 18/57] minor updates --- ARCs/arc-0056.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 94b84b2e7..31368e52d 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -28,7 +28,7 @@ Every application is described via the following interface which is an extension ```ts /** Describes the entire contract. This interface is an extension of the interface described in ARC-4 */ interface Contract { - /** The ARCs used and/or supported by this contract */ + /** The ARCs used and/or supported by this contract. All contracts implicity support ARC4 and ARC56 */ arcs: number[], /** A user-friendly name for the contract */ name: string; @@ -86,7 +86,7 @@ interface Contract { call: ('NoOp' | 'OptIn' | 'CloseOut' | 'ClearState' | 'UpdateApplication' | 'DeleteApplication')[]; }; /** Information about the TEAL */ - sourceInfo: SourceInfo; + sourceInfo?: SourceInfo[]; /** The pre-compiled TEAL that may contain template variables. MUST be omitted if included as part of ARC23, but otherwise MUST be defined. */ source?: { /** The approval program */ @@ -157,7 +157,7 @@ interface Method { /** Recommended box references to include */ boxes?: { /** The app ID for the box */ - app: number; + app?: number; /** The base64 encoded box key */ key: string; /** The number of bytes being read from the box */ From e6115f019c8453402d852e527435815b57af4bd2 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Mon, 29 Apr 2024 14:28:33 -0400 Subject: [PATCH 19/57] pushint/pushbyte opcdes, formatting --- ARCs/arc-0056.md | 59 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 31368e52d..cf792aa7f 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -11,11 +11,12 @@ created: 2023-11-14 requires: 4, 22, 28 --- - ## Abstract + This ARC takes the existing JSON description of a contract as described in [ARC-4](./arc-0004.md) and adds more fields for the purpose of client interaction ## Motivation + The data provided by ARC-4 is missing a lot of critical information that clients should know when interacting with an app. This means ARC-4 is insufficient to generate type-safe clients that provide a superior developer experience. On the other hand, [ARC-32](./arc-0032.md) provides the vast majority of useful information that can be used to generate typed clients, but requires a separate JSON file on top of the ARC-4 json file, which adds extra complexity and cognitive overhead. @@ -23,13 +24,14 @@ On the other hand, [ARC-32](./arc-0032.md) provides the vast majority of useful ## Specification ### Contract Interface + Every application is described via the following interface which is an extension of the `Contract` interface described in [ARC-4](./arc-0004.md). ```ts /** Describes the entire contract. This interface is an extension of the interface described in ARC-4 */ interface Contract { /** The ARCs used and/or supported by this contract. All contracts implicity support ARC4 and ARC56 */ - arcs: number[], + arcs: number[]; /** A user-friendly name for the contract */ name: string; /** Optional, user-friendly description for the interface */ @@ -41,7 +43,7 @@ interface Contract { /** * The key is the base64 genesis hash of the network, and the value contains * information about the deployed contract in the network indicated by the - * key. A key containing the human-readable name of the network MAY be + * key. A key containing the human-readable name of the network MAY be * included, but the corresponding genesis hash key MUST also be defined */ [network: string]: { @@ -81,9 +83,16 @@ interface Contract { /** Supported bare actions for the contract. An action is a combination of call/create and an OnComplete */ bareActions: { /** OnCompletes this method allows when appID === 0 */ - create: ('NoOp' | 'OptIn' | 'DeleteApplication')[]; + create: ("NoOp" | "OptIn" | "DeleteApplication")[]; /** OnCompletes this method allows when appID !== 0 */ - call: ('NoOp' | 'OptIn' | 'CloseOut' | 'ClearState' | 'UpdateApplication' | 'DeleteApplication')[]; + call: ( + | "NoOp" + | "OptIn" + | "CloseOut" + | "ClearState" + | "UpdateApplication" + | "DeleteApplication" + )[]; }; /** Information about the TEAL */ sourceInfo?: SourceInfo[]; @@ -142,9 +151,16 @@ interface Method { /** an action is a combination of call/create and an OnComplete */ actions: { /** OnCompletes this method allows when appID === 0 */ - create: ('NoOp' | 'OptIn' | 'DeleteApplication')[]; + create: ("NoOp" | "OptIn" | "DeleteApplication")[]; /** OnCompletes this method allows when appID !== 0 */ - call: ('NoOp' | 'OptIn' | 'CloseOut' | 'ClearState' | 'UpdateApplication' | 'DeleteApplication')[]; + call: ( + | "NoOp" + | "OptIn" + | "CloseOut" + | "ClearState" + | "UpdateApplication" + | "DeleteApplication" + )[]; }; /** If this method does not write anything to the ledger (ARC-22) */ readonly: boolean; @@ -199,7 +215,6 @@ interface Event { } ``` - ### Type Interfaces The types defined in [ARC-4](./arc-0004.md) may not fully described the best way to use the ABI values as intended by the contract developers. These type interfaces are intended to supplement ABI types so clients can interact with the contract as intended. @@ -212,7 +227,7 @@ type ABIType = string; type StructName = string; /** Raw byteslice without the length prefixed that is specified in ARC-4 */ -type AVMBytes = 'bytes'; +type AVMBytes = "bytes"; /** Mapping of named structs to the ABI type of their fields */ interface StructFields { @@ -266,18 +281,20 @@ interface SourceInfo { ### Template Variables -Template variables are variables in the TEAL that should be substitued prior to compilation. Template variables **MUST** be an argument to either `pushints` or `pusbytes`. Using these opcodes is important to ensure that the program does not add them to the constant blocks. +Template variables are variables in the TEAL that should be substitued prior to compilation. Template variables **MUST** be an argument to either `pushint` or `pusbyte` (not the pseudo opcodes `int` or `byte`). Using these opcodes is important to ensure that the program does not add them to the constant blocks. #### Examples + ##### Valid + ``` -pushints TMPL_FOO -pushbytes TMPL_BAR +pushint TMPL_FOO +pushbyte TMPL_BAR ``` #### Invalid -Template variables MUST use pushints or pushbytes +Template variables MUST use `pushint` or `pushbyte` ``` int TMPL_FOO @@ -287,16 +304,17 @@ byte TMPL_BYTE Template variables MUST be the entire argument ``` -pushints 123TMPL_FOO -pusbytes 0xdeadTMPL_BAR +pushint 123TMPL_FOO +pusbyte 0xdeadTMPL_BAR ``` ## Rationale + ARC-32 essentially addresses the same problem, but it requires the generation of two separate JSON files and the ARC-32 JSON file contains the ARC-4 JSON file within it (redundant information). The goal of this ARC is to create one JSON schema that is backwards compatible with ARC-4 clients, but contains the relevant information needed to automatically generate comprehensive client experiences. ### State -Describes all of the state that MAY exist in the app and how one should decode values. The schema provides the required schema when creating the app. +Describes all of the state that MAY exist in the app and how one should decode values. The schema provides the required schema when creating the app. ### Named Structs @@ -304,19 +322,24 @@ It is common for high-level languages to support named structs, which gives name ### Action -This is one of the biggest deviation from ARC-32, but provides a much simpler interface to describe and understand what any given method can do. +This is one of the biggest deviation from ARC-32, but provides a much simpler interface to describe and understand what any given method can do. ## Backwards Compatibility + The JSON schema defined in this ARC should be compatible with all ARC-4 clients, provided they don't do any strict schema checking for extraneous fields. ## Test Cases + NA ## Reference Implementation + TODO ## Security Considerations -The type values used in methods **MUST** be correct, because if they were not then the method would not be callable. For state, however, it is possible to have an incorrect type encoding defined. Any significant security concern from this possibility is not immediately evident, but it is worth considering. + +The type values used in methods **MUST** be correct, because if they were not then the method would not be callable. For state, however, it is possible to have an incorrect type encoding defined. Any significant security concern from this possibility is not immediately evident, but it is worth considering. ## Copyright + Copyright and related rights waived via CCO. From fd8fe2ad3b549ee22fecb4e264e62b1a72da4e86 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Mon, 29 Apr 2024 14:29:16 -0400 Subject: [PATCH 20/57] add @robdmoore as author --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index cf792aa7f..5b7aa7914 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -2,7 +2,7 @@ arc: 56 title: Extended App Description description: Adds information to the ABI JSON description -author: Joe Polny (@joe-p) +author: Joe Polny (@joe-p), Rob Moore (@robdmoore) discussions-to: https://github.com/algorandfoundation/ARCs/issues/258 status: Draft type: Standards Track From 89a6c0c060923371da821540fc39af21f55a1f95 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Mon, 29 Apr 2024 15:01:33 -0400 Subject: [PATCH 21/57] error -> errorMessage --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 5b7aa7914..cb450f84e 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -275,7 +275,7 @@ interface SourceInfo { /** The program counter offset(s) that correspond to this line of TEAL */ pc?: Array; /** A human-readable string that describes the error when the program fails at this given line of TEAL */ - error?: string; + errorMessage?: string; } ``` From 35fd3fcfef5ed52e1ca092c701dc4c3f9d889ce2 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Mon, 6 May 2024 07:51:31 -0400 Subject: [PATCH 22/57] Storage interface update --- ARCs/arc-0056.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index cb450f84e..3d362660e 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -242,6 +242,8 @@ These interfaces properly describe how app storage is access within the contract ```ts /** Describes a single key in app storage */ interface StorageKey { + /** Human readable name */ + name: string; /** Description of what this storage key holds */ desc?: string; /** The type of the key */ @@ -252,7 +254,10 @@ interface StorageKey { key: string; } +/** Describes a mapping of key-value pairs in storage */ interface StorageMap { + /** Human readable name */ + name: string; /** Description of what the key-value pairs in this mapping hold */ desc?: string; /** The type of the keys in the map */ @@ -260,7 +265,7 @@ interface StorageMap { /** The type of the values in the map */ valueType: ABIType | AVMBytes | StructName; /** The prefix of the map, encoded as a utf-8 string */ - prefix: string; + prefix?: string; } ``` From 8572596a4741b18ea35b7c9e985451c097db8337 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 8 May 2024 07:34:58 -0400 Subject: [PATCH 23/57] use names as keys for template variables and state keys/maps --- ARCs/arc-0056.md | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 3d362660e..7871fe0dd 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -67,17 +67,17 @@ interface Contract { bytes: number; }; }; - /** Describes single key-value pairs in the application's state */ + /** Mapping of human-readable names to StorageKey objects */ keys: { - global: StorageKey[]; - local: StorageKey[]; - box: StorageKey[]; + global: { [name: string]: StorageKey }; + local: { [name: string]: StorageKey }; + box: { [name: string]: StorageKey }; }; - /** Describes key-value maps in the application's state */ + /** Mapping of human-readable names to StorageMap objects */ maps: { - global: StorageMap[]; - local: StorageMap[]; - box: StorageMap[]; + global: { [name: string]: StorageMap }; + local: { [name: string]: StorageMap }; + box: { [name: string]: StorageMap }; }; }; /** Supported bare actions for the contract. An action is a combination of call/create and an OnComplete */ @@ -105,13 +105,10 @@ interface Contract { }; /** ARC-28 events that MAY be emitted by this contract */ events?: Array; - /** Template Variables */ + /** A mapping of template variable names as they appear in the teal (not including TMPL_ prefix) and their respecive types */ templateVariables?: { - /** The name of the template variable as it appears in the TEAL */ - name: string; - /** The type of the value expected in the template variable */ - type: ABIType | AVMBytes | StructName; - }[]; + [name: string]: ABIType | AVMBytes | StructName; + }; } ``` @@ -242,8 +239,6 @@ These interfaces properly describe how app storage is access within the contract ```ts /** Describes a single key in app storage */ interface StorageKey { - /** Human readable name */ - name: string; /** Description of what this storage key holds */ desc?: string; /** The type of the key */ @@ -256,8 +251,6 @@ interface StorageKey { /** Describes a mapping of key-value pairs in storage */ interface StorageMap { - /** Human readable name */ - name: string; /** Description of what the key-value pairs in this mapping hold */ desc?: string; /** The type of the keys in the map */ From ac0a9b14e3b796993ea9c91df6090e9b120c922d Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 8 May 2024 14:37:08 -0400 Subject: [PATCH 24/57] make readonly optional --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 7871fe0dd..4db1074ad 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -160,7 +160,7 @@ interface Method { )[]; }; /** If this method does not write anything to the ledger (ARC-22) */ - readonly: boolean; + readonly?: boolean; /** ARC-28 events that MAY be emitted by this method */ events?: Array; /** Information that clients can use when calling the method */ From 05cd0d58200d3807ed83db38bb9777dfadc8fc5d Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Mon, 20 May 2024 19:25:12 -0400 Subject: [PATCH 25/57] add scratchVariables --- ARCs/arc-0056.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 4db1074ad..73fbffe57 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -109,6 +109,13 @@ interface Contract { templateVariables?: { [name: string]: ABIType | AVMBytes | StructName; }; + /** The scratch variables used during runtime */ + scratchVariables: { + [name: string]: { + slot: number; + type: ABIType | AVMBytes | StructName; + }; + }; } ``` From ab956a712eeb5f436e0d454a346f04428b04f346 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Mon, 20 May 2024 19:25:37 -0400 Subject: [PATCH 26/57] add value? to templateVariables --- ARCs/arc-0056.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 73fbffe57..ffbfec389 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -105,9 +105,14 @@ interface Contract { }; /** ARC-28 events that MAY be emitted by this contract */ events?: Array; - /** A mapping of template variable names as they appear in the teal (not including TMPL_ prefix) and their respecive types */ + /** A mapping of template variable names as they appear in the teal (not including TMPL_ prefix) to their respecive types and values (if applicable) */ templateVariables?: { - [name: string]: ABIType | AVMBytes | StructName; + [name: string]: { + /** The type of the template variable */ + type: ABIType | AVMBytes | StructName; + /** If given, the the base64 encoded value used for the given app/program */ + value?: string; + }; }; /** The scratch variables used during runtime */ scratchVariables: { From 22372b2d283e1c2ad61ff45ac863350250f8a563 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Mon, 20 May 2024 19:26:53 -0400 Subject: [PATCH 27/57] add btyeCode --- ARCs/arc-0056.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index ffbfec389..1ffd3c93a 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -96,13 +96,22 @@ interface Contract { }; /** Information about the TEAL */ sourceInfo?: SourceInfo[]; - /** The pre-compiled TEAL that may contain template variables. MUST be omitted if included as part of ARC23, but otherwise MUST be defined. */ + /** The pre-compiled TEAL that may contain template variables. MUST be omitted if included as part of ARC23 */ source?: { /** The approval program */ approval: string; /** The clear program */ clear: string; }; + /** The compiled bytecode for the application. MUST be omitted if included as part of ARC23 */ + byteCode?: { + /** The compiler used to generate the bytecode */ + compiler: "algod" | "puya"; + /** The approval program */ + approval: string; + /** The clear program */ + clear: string; + }; /** ARC-28 events that MAY be emitted by this contract */ events?: Array; /** A mapping of template variable names as they appear in the teal (not including TMPL_ prefix) to their respecive types and values (if applicable) */ From 8ee78668b3f706c4192c3c86d6a710294eeb967b Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Mon, 20 May 2024 19:27:16 -0400 Subject: [PATCH 28/57] make teal optional --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 1ffd3c93a..3788eb9d9 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -290,7 +290,7 @@ This interface gives clients more information about the contract's source code. ```ts interface SourceInfo { /** The line of pre-compiled TEAL */ - teal: number; + teal?: number; /** The program counter offset(s) that correspond to this line of TEAL */ pc?: Array; /** A human-readable string that describes the error when the program fails at this given line of TEAL */ From f82a2fa4249d7e2646b163277a4b4a2b343b985a Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Mon, 20 May 2024 19:32:00 -0400 Subject: [PATCH 29/57] make scratchVariables optional --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 3788eb9d9..6ed423be5 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -124,7 +124,7 @@ interface Contract { }; }; /** The scratch variables used during runtime */ - scratchVariables: { + scratchVariables?: { [name: string]: { slot: number; type: ABIType | AVMBytes | StructName; From ad5d0338ee2184c7430cb5ca5c0fcaf4628b1d93 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Mon, 20 May 2024 20:06:39 -0400 Subject: [PATCH 30/57] add compilerVersion --- ARCs/arc-0056.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 6ed423be5..9eaf44148 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -111,6 +111,13 @@ interface Contract { approval: string; /** The clear program */ clear: string; + /** Compiler version information */ + compilerVersion: { + major: number; + minor: number; + patch: number; + commit?: string; + }; }; /** ARC-28 events that MAY be emitted by this contract */ events?: Array; From e540d921502f19c720b64d8df1f09563158ca348 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Mon, 20 May 2024 20:19:37 -0400 Subject: [PATCH 31/57] compilerInfo --- ARCs/arc-0056.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 9eaf44148..e774ae6ae 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -105,12 +105,15 @@ interface Contract { }; /** The compiled bytecode for the application. MUST be omitted if included as part of ARC23 */ byteCode?: { - /** The compiler used to generate the bytecode */ - compiler: "algod" | "puya"; /** The approval program */ approval: string; /** The clear program */ clear: string; + }; + /** Information used to get the given byteCode and/or PC values in sourceInfo. MUST be given if byteCode or PC values are present */ + compilerInfo?: { + /** The name of the compiler */ + compiler: "algod" | "puya"; /** Compiler version information */ compilerVersion: { major: number; From 7b3982bc04ea4fe6a920989a68ccd6fc88499e8a Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Sun, 28 Jul 2024 13:45:44 -0400 Subject: [PATCH 32/57] add disassembledTeal to Sourceinfo --- ARCs/arc-0056.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index e774ae6ae..9729a8093 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -305,6 +305,8 @@ interface SourceInfo { pc?: Array; /** A human-readable string that describes the error when the program fails at this given line of TEAL */ errorMessage?: string; + /** The line of the dissasembled TEAL this line of pre-compiled TEAL corresponds to */ + disassembledTeal?: number; } ``` From f30b5f649a3986b43114c1ee998c4546db62b2b5 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Tue, 6 Aug 2024 17:28:35 -0400 Subject: [PATCH 33/57] base64 prefix --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 9729a8093..78a1d1f9c 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -288,7 +288,7 @@ interface StorageMap { keyType: ABIType | AVMBytes | StructName; /** The type of the values in the map */ valueType: ABIType | AVMBytes | StructName; - /** The prefix of the map, encoded as a utf-8 string */ + /** The base64-encoded prefix of the map keys*/ prefix?: string; } ``` From 59edfa884947163136ab290339eca5c7ed35d575 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 4 Sep 2024 06:18:50 -0400 Subject: [PATCH 34/57] add approval/clear keys to sourceInfo --- ARCs/arc-0056.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 78a1d1f9c..e7ec9d66d 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -94,8 +94,13 @@ interface Contract { | "DeleteApplication" )[]; }; - /** Information about the TEAL */ - sourceInfo?: SourceInfo[]; + /** Information about the TEAL programs */ + sourceInfo?: { + /** Approval program information */ + approval: SourceInfo[]; + /** Clear program information */ + clear: SourceInfo[]; + }; /** The pre-compiled TEAL that may contain template variables. MUST be omitted if included as part of ARC23 */ source?: { /** The approval program */ From 7f5816aa4a557ec97f114395da6f816e98fb3ef1 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 11 Sep 2024 16:30:48 -0400 Subject: [PATCH 35/57] commit -> commitHash --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index e7ec9d66d..1108a79b4 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -124,7 +124,7 @@ interface Contract { major: number; minor: number; patch: number; - commit?: string; + commitHash?: string; }; }; /** ARC-28 events that MAY be emitted by this contract */ From 9908f86e2459652209b2eed66309c7d136aced2b Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 11 Sep 2024 16:34:12 -0400 Subject: [PATCH 36/57] pushbytes for TMPL --- ARCs/arc-0056.md | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 1108a79b4..cb8a4302e 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -317,15 +317,14 @@ interface SourceInfo { ### Template Variables -Template variables are variables in the TEAL that should be substitued prior to compilation. Template variables **MUST** be an argument to either `pushint` or `pusbyte` (not the pseudo opcodes `int` or `byte`). Using these opcodes is important to ensure that the program does not add them to the constant blocks. +Template variables are variables in the TEAL that should be substitued prior to compilation. Template variables **MUST** be an argument to `pusbytes` (not the pseudo opcode `byte`) to ensure that the program does not add them to the constant blocks. `pushint` (or `int`) is not used due to the variance in integer byte sizes which impact source mapping. #### Examples ##### Valid ``` -pushint TMPL_FOO -pushbyte TMPL_BAR +pushbytes TMPL_FOO ``` #### Invalid @@ -333,15 +332,19 @@ pushbyte TMPL_BAR Template variables MUST use `pushint` or `pushbyte` ``` -int TMPL_FOO -byte TMPL_BYTE +pushbytes TMPL_FOO ``` Template variables MUST be the entire argument ``` -pushint 123TMPL_FOO -pusbyte 0xdeadTMPL_BAR +pusbytes 0xdeadTMPL_BAR +``` + +Template variables MUST NOT be used with `pushint` + +``` +pushint TMPL_FOO ``` ## Rationale @@ -379,3 +382,7 @@ The type values used in methods **MUST** be correct, because if they were not th ## Copyright Copyright and related rights waived via CCO. + +``` + +``` From faf5f4bddf139341e52aabeb999a7413999769e3 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 18 Sep 2024 11:56:59 -0400 Subject: [PATCH 37/57] move networks tsdoc --- ARCs/arc-0056.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index cb8a4302e..3e5b6a48d 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -37,15 +37,13 @@ interface Contract { /** Optional, user-friendly description for the interface */ desc?: string; /** - * Optional object listing the contract instances across different networks + * Optional object listing the contract instances across different networks. + * The key is the base64 genesis hash of the network, and the value contains + * information about the deployed contract in the network indicated by the + * key. A key containing the human-readable name of the network MAY be + * included, but the corresponding genesis hash key MUST also be define */ networks?: { - /** - * The key is the base64 genesis hash of the network, and the value contains - * information about the deployed contract in the network indicated by the - * key. A key containing the human-readable name of the network MAY be - * included, but the corresponding genesis hash key MUST also be defined - */ [network: string]: { /** The app ID of the deployed contract in this network */ appID: number; From 506acbdd69f522ac0ef25a1ea361621dc502bc12 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 18 Sep 2024 12:31:09 -0400 Subject: [PATCH 38/57] state default values --- ARCs/arc-0056.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 3e5b6a48d..4fbf763f5 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -167,8 +167,20 @@ interface Method { name?: string; /** Optional, user-friendly description for the argument */ desc?: string; - /** The default value that clients should use. MUST be base64 encoded bytes */ - defaultValue?: string; + /** The default value that clients should use. */ + defaultValue?: { + /** Base64 encoded bytes or uint64 */ + data: string | bigint; + /** How the data is encoded. This is the encoding for the data provided here, not the arg type */ + type: ABIType | AVMBytes; + /** Where the default value is coming from + * - box: The data key signifies the box key to read the value from + * - global: The data key signifies the global state key to read the value from + * - local: The data key signifies the local state key to read the value from (for the sender) + * - literal: the value is a literal and should be passed directly as the argument + */ + source: 'box' | 'global' | 'local' | 'literal; + }; }>; /** Information about the method's return value */ returns: { From d8d4c462642578c2286f75c45f30b68c99065ac0 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 18 Sep 2024 12:34:12 -0400 Subject: [PATCH 39/57] type/struct tsdoc --- ARCs/arc-0056.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 4fbf763f5..10e2f8a20 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -159,7 +159,7 @@ interface Method { desc?: string; /** The arguments of the method, in order */ args: Array<{ - /** The type of the argument */ + /** The type of the argument. The `struct` field should also be checked to determine if this arg is a struct. */ type: ABIType; /** If the type is a struct, the name of the struct */ struct?: StructName; @@ -184,7 +184,7 @@ interface Method { }>; /** Information about the method's return value */ returns: { - /** The type of the return value, or "void" to indicate no return value. */ + /** The type of the return value, or "void" to indicate no return value. The `struct` field should also be checked to determine if this return value is a struct. */ type: ABIType; /** If the type is a struct, the name of the struct */ struct?: StructName; @@ -246,7 +246,7 @@ interface Event { desc?: string; /** The arguments of the event, in order */ args: Array<{ - /** The type of the argument */ + /** The type of the argument. The `struct` field should also be checked to determine if this arg is a struct. */ type: ABIType; /** Optional, user-friendly name for the argument */ name?: string; From 6bc830ce8de599bb0a6eb5c9ca6c35793b81835d Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 18 Sep 2024 12:37:35 -0400 Subject: [PATCH 40/57] StructFields -> StructField[] --- ARCs/arc-0056.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 10e2f8a20..3749163cb 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -49,8 +49,8 @@ interface Contract { appID: number; }; }; - /** Named structs use by the application */ - structs: { [structName: StructName]: StructFields }; + /** Named structs use by the application. Each struct field appears in the same order as ABI encoding. */ + structs: { [structName: StructName]: StructField[] }; /** All of the methods that the contract implements */ methods: Method[]; state: { @@ -272,9 +272,12 @@ type StructName = string; /** Raw byteslice without the length prefixed that is specified in ARC-4 */ type AVMBytes = "bytes"; -/** Mapping of named structs to the ABI type of their fields */ -interface StructFields { - [fieldName: string]: ABIType | StructFields; +/** Information about a single field in a struct */ +interface StructField = { + /** The name of the struct field */ + name: string; + /** The type of the struct field's value */ + type: ABIType | StructName; } ``` From da85edf25b6c4aed1ab47fce80a8cedd38f85635 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 18 Sep 2024 12:42:52 -0400 Subject: [PATCH 41/57] AVMString --- ARCs/arc-0056.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 3749163cb..2d462f510 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -131,7 +131,7 @@ interface Contract { templateVariables?: { [name: string]: { /** The type of the template variable */ - type: ABIType | AVMBytes | StructName; + type: ABIType | AVMString | AVMBytes | StructName; /** If given, the the base64 encoded value used for the given app/program */ value?: string; }; @@ -140,7 +140,7 @@ interface Contract { scratchVariables?: { [name: string]: { slot: number; - type: ABIType | AVMBytes | StructName; + type: ABIType | AVMString | AVMBytes | StructName; }; }; } @@ -172,7 +172,7 @@ interface Method { /** Base64 encoded bytes or uint64 */ data: string | bigint; /** How the data is encoded. This is the encoding for the data provided here, not the arg type */ - type: ABIType | AVMBytes; + type: ABIType | AVMBytes | AVMString; /** Where the default value is coming from * - box: The data key signifies the box key to read the value from * - global: The data key signifies the global state key to read the value from @@ -270,7 +270,10 @@ type ABIType = string; type StructName = string; /** Raw byteslice without the length prefixed that is specified in ARC-4 */ -type AVMBytes = "bytes"; +type AVMBytes = "AVMBytes"; + +/** A string without the length prefix that is specified in ARC-4 */ +type AVMString = "AVMString"; /** Information about a single field in a struct */ interface StructField = { @@ -291,9 +294,9 @@ interface StorageKey { /** Description of what this storage key holds */ desc?: string; /** The type of the key */ - keyType: ABIType | AVMBytes | StructName; + keyType: ABIType | AVMString | AVMBytes | StructName; /** The type of the value */ - valueType: ABIType | AVMBytes | StructName; + valueType: ABIType | AVMString | AVMBytes | StructName; /** The bytes of the key encoded as base64 */ key: string; } @@ -303,9 +306,9 @@ interface StorageMap { /** Description of what the key-value pairs in this mapping hold */ desc?: string; /** The type of the keys in the map */ - keyType: ABIType | AVMBytes | StructName; + keyType: ABIType | AVMString | AVMBytes | StructName; /** The type of the values in the map */ - valueType: ABIType | AVMBytes | StructName; + valueType: ABIType | AVMString | AVMBytes | StructName; /** The base64-encoded prefix of the map keys*/ prefix?: string; } From 3ef93fc6efb6427a79018216bd3359cdd1a297f4 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 25 Sep 2024 09:50:48 -0400 Subject: [PATCH 42/57] StructField[] --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 2d462f510..32eda666a 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -280,7 +280,7 @@ interface StructField = { /** The name of the struct field */ name: string; /** The type of the struct field's value */ - type: ABIType | StructName; + type: ABIType | StructName | StructField[]; } ``` From e577cfb32d93a84e7700a82b476e004ed7b09dfd Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 25 Sep 2024 09:51:44 -0400 Subject: [PATCH 43/57] specify utf-8 --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 32eda666a..d4b308a76 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -272,7 +272,7 @@ type StructName = string; /** Raw byteslice without the length prefixed that is specified in ARC-4 */ type AVMBytes = "AVMBytes"; -/** A string without the length prefix that is specified in ARC-4 */ +/** A utf-8 string without the length prefix that is specified in ARC-4 */ type AVMString = "AVMString"; /** Information about a single field in a struct */ From 58a133d750db38efac56ddfcf9a97f100a523692 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 25 Sep 2024 09:56:23 -0400 Subject: [PATCH 44/57] AVMUint64 and AVMType --- ARCs/arc-0056.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index d4b308a76..49510804c 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -131,7 +131,7 @@ interface Contract { templateVariables?: { [name: string]: { /** The type of the template variable */ - type: ABIType | AVMString | AVMBytes | StructName; + type: ABIType | AVMType | StructName; /** If given, the the base64 encoded value used for the given app/program */ value?: string; }; @@ -140,7 +140,7 @@ interface Contract { scratchVariables?: { [name: string]: { slot: number; - type: ABIType | AVMString | AVMBytes | StructName; + type: ABIType | AVMType | StructName; }; }; } @@ -172,7 +172,7 @@ interface Method { /** Base64 encoded bytes or uint64 */ data: string | bigint; /** How the data is encoded. This is the encoding for the data provided here, not the arg type */ - type: ABIType | AVMBytes | AVMString; + type: ABIType | AVMType; /** Where the default value is coming from * - box: The data key signifies the box key to read the value from * - global: The data key signifies the global state key to read the value from @@ -275,6 +275,12 @@ type AVMBytes = "AVMBytes"; /** A utf-8 string without the length prefix that is specified in ARC-4 */ type AVMString = "AVMString"; +/** A 64-bit unsigned integer */ +type AVMUint64 = "AVMUint64"; + +/** A native AVM type */ +type AVMType = AVMBytes | AVMString | AVMUint64; + /** Information about a single field in a struct */ interface StructField = { /** The name of the struct field */ @@ -294,9 +300,9 @@ interface StorageKey { /** Description of what this storage key holds */ desc?: string; /** The type of the key */ - keyType: ABIType | AVMString | AVMBytes | StructName; + keyType: ABIType | AVMType | StructName; /** The type of the value */ - valueType: ABIType | AVMString | AVMBytes | StructName; + valueType: ABIType | AVMType | StructName; /** The bytes of the key encoded as base64 */ key: string; } @@ -306,9 +312,9 @@ interface StorageMap { /** Description of what the key-value pairs in this mapping hold */ desc?: string; /** The type of the keys in the map */ - keyType: ABIType | AVMString | AVMBytes | StructName; + keyType: ABIType | AVMType | StructName; /** The type of the values in the map */ - valueType: ABIType | AVMString | AVMBytes | StructName; + valueType: ABIType | AVMType | StructName; /** The base64-encoded prefix of the map keys*/ prefix?: string; } From aa79e866bb5eecf90b7d390002205d64ff55101c Mon Sep 17 00:00:00 2001 From: Joe Polny <50534337+joe-p@users.noreply.github.com> Date: Wed, 2 Oct 2024 19:27:42 -0400 Subject: [PATCH 45/57] Apply suggestions from code review Co-authored-by: Rob Moore (MakerX) --- ARCs/arc-0056.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 49510804c..9113b7623 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -179,7 +179,7 @@ interface Method { * - local: The data key signifies the local state key to read the value from (for the sender) * - literal: the value is a literal and should be passed directly as the argument */ - source: 'box' | 'global' | 'local' | 'literal; + source: 'box' | 'global' | 'local' | 'literal'; }; }>; /** Information about the method's return value */ @@ -282,7 +282,7 @@ type AVMUint64 = "AVMUint64"; type AVMType = AVMBytes | AVMString | AVMUint64; /** Information about a single field in a struct */ -interface StructField = { +interface StructField { /** The name of the struct field */ name: string; /** The type of the struct field's value */ From 35a19b31606ae56c5b53da8c5d84b5822ac28582 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Thu, 10 Oct 2024 15:22:04 -0400 Subject: [PATCH 46/57] ProgramSourceInfo --- ARCs/arc-0056.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 9113b7623..9e3d96600 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -95,9 +95,9 @@ interface Contract { /** Information about the TEAL programs */ sourceInfo?: { /** Approval program information */ - approval: SourceInfo[]; + approval: ProgramSourceInfo; /** Clear program information */ - clear: SourceInfo[]; + clear: ProgramSourceInfo; }; /** The pre-compiled TEAL that may contain template variables. MUST be omitted if included as part of ARC23 */ source?: { @@ -178,8 +178,8 @@ interface Method { * - global: The data key signifies the global state key to read the value from * - local: The data key signifies the local state key to read the value from (for the sender) * - literal: the value is a literal and should be passed directly as the argument - */ - source: 'box' | 'global' | 'local' | 'literal'; + */ + source: "box" | "global" | "local" | "literal"; }; }>; /** Information about the method's return value */ @@ -322,9 +322,19 @@ interface StorageMap { ### SourceInfo Interface -This interface gives clients more information about the contract's source code. +These interfaces give clients more information about the contract's source code. ```ts +interface ProgramSourceInfo { + /** The source information for the program */ + sourceInfo: SourceInfo[]; + /** How the program counter offset is calculated + * - none: The pc values in sourceInfo are not offset + * - cblocks: The pc values in sourceInfo are offset by PC of the last cblock at the top of the program + */ + pcOffsetMethod: "none" | "cblocks"; +} + interface SourceInfo { /** The line of pre-compiled TEAL */ teal?: number; From 3476dad18b0dba6cbb2670ac3c2c7cefcb0fd7fe Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Thu, 10 Oct 2024 15:32:09 -0400 Subject: [PATCH 47/57] added method as default arg source --- ARCs/arc-0056.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 9e3d96600..81c95539c 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -178,8 +178,9 @@ interface Method { * - global: The data key signifies the global state key to read the value from * - local: The data key signifies the local state key to read the value from (for the sender) * - literal: the value is a literal and should be passed directly as the argument + * - method: The utf8 signature of the method in this contract to call to get the default value. If the method has arguments, they all must have default values. The method **MUST** be readonly so simulate can be used to get the default value. */ - source: "box" | "global" | "local" | "literal"; + source: "box" | "global" | "local" | "literal" | "method"; }; }>; /** Information about the method's return value */ From 1e31ba0e358ffa9444f2ec04393bf5c6cb6ae3b6 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Thu, 10 Oct 2024 15:50:07 -0400 Subject: [PATCH 48/57] update template variables spec --- ARCs/arc-0056.md | 76 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 81c95539c..e1db564bc 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -350,35 +350,21 @@ interface SourceInfo { ### Template Variables -Template variables are variables in the TEAL that should be substitued prior to compilation. Template variables **MUST** be an argument to `pusbytes` (not the pseudo opcode `byte`) to ensure that the program does not add them to the constant blocks. `pushint` (or `int`) is not used due to the variance in integer byte sizes which impact source mapping. +Template variables are variables in the TEAL that should be substitued prior to compilation. The usage of the variable **MUST** appear in the TEAL starting with `TMPL_`. Template variables **MUST** be an argument to either `bytecblock` or `intcblock`. If a program has template variables, `bytecblock` and `intcblock` **MUST** be the first two opcodes in the program (unless one is not used). -#### Examples - -##### Valid - -``` -pushbytes TMPL_FOO -``` - -#### Invalid - -Template variables MUST use `pushint` or `pushbyte` +#### Example +```js +#pragma version 10 +bytecblock 0xdeadbeef TMPL_FOO +intcblock 0x12345678 TMPL_BAR ``` -pushbytes TMPL_FOO -``` - -Template variables MUST be the entire argument -``` -pusbytes 0xdeadTMPL_BAR -``` +### Dynamic Template Variables -Template variables MUST NOT be used with `pushint` +When a program has a template variable with a dynamic length, the `pcOffsetMethod` in `ProgramSourceInfo` **MUST** be `cblocks`. The `pc` value in each `SourceInfo` **MUST** be the pc determined at compilation minus the last `pc` value of the last `cblock` at compilation. -``` -pushint TMPL_FOO -``` +When a client is leveraging a source map with `cblocks` as the `pcOffsetMethod`, it **MUST** determine the `pc` value by parsing the bytecode to get the PC value of the last `cblock` at the top of the program. See the reference implementation section for an example of how to do this. ## Rationale @@ -406,7 +392,49 @@ NA ## Reference Implementation -TODO +### Calculating cblock Offsets + +```ts +const BYTE_CBLOCK = 38; +const INT_CBLOCK = 32; + +function parseConstantBlocks(bytes: number[]) { + const programSize = bytes.length; + bytes.shift(); // remove version + const offsets: { bytecblock?: number; intcblock?: number; cblocks: number } = + { cblocks: 0 }; + + while (bytes.length > 0) { + const byte = bytes.shift()!; + + if (byte === BYTE_CBLOCK || byte === INT_CBLOCK) { + const isBytecblock = byte === BYTE_CBLOCK; + const valuesRemaining = bytes.shift()!; + + for (let i = 0; i < valuesRemaining; i++) { + if (isBytecblock) { + // byte is the length of the next element + bytes.splice(0, bytes.shift()!); + } else { + // intcblock is a uvarint, so we need to keep reading until we find the end (MSB is not set) + while ((bytes.shift()! & 0x80) !== 0) {} + } + } + + offsets[isBytecblock ? "bytecblock" : "intcblock"] = + programSize - bytes.length; + + if (bytes[0] !== BYTE_CBLOCK && bytes[0] !== INT_CBLOCK) { + // if the next opcode isn't a constant block, we're done + break; + } + } + } + + offsets.cblocks = Math.max(...Object.values(offsets)); + return offsets; +} +``` ## Security Considerations From 19c62692572f111edd93cf673863ac64bd33c84e Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Fri, 11 Oct 2024 07:52:28 -0400 Subject: [PATCH 49/57] only inlcude pc and errorMessage in SourceInfo --- ARCs/arc-0056.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index e1db564bc..53084450b 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -337,14 +337,10 @@ interface ProgramSourceInfo { } interface SourceInfo { - /** The line of pre-compiled TEAL */ - teal?: number; - /** The program counter offset(s) that correspond to this line of TEAL */ - pc?: Array; - /** A human-readable string that describes the error when the program fails at this given line of TEAL */ - errorMessage?: string; - /** The line of the dissasembled TEAL this line of pre-compiled TEAL corresponds to */ - disassembledTeal?: number; + /** The program counter value(s). Could be offset if pcOffsetMethod is not "none" */ + pc: Array; + /** A human-readable string that describes the error when the program fails at the given PC */ + errorMessage: string; } ``` From 017c6e33be711d3349d234d5e5095a95a3e0f49f Mon Sep 17 00:00:00 2001 From: Joe Polny <50534337+joe-p@users.noreply.github.com> Date: Wed, 16 Oct 2024 08:18:38 -0400 Subject: [PATCH 50/57] Apply suggestions from code review Co-authored-by: Daniel McGregor --- ARCs/arc-0056.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 53084450b..eee7689b7 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -127,7 +127,7 @@ interface Contract { }; /** ARC-28 events that MAY be emitted by this contract */ events?: Array; - /** A mapping of template variable names as they appear in the teal (not including TMPL_ prefix) to their respecive types and values (if applicable) */ + /** A mapping of template variable names as they appear in the teal (not including TMPL_ prefix) to their respective types and values (if applicable) */ templateVariables?: { [name: string]: { /** The type of the template variable */ @@ -331,7 +331,7 @@ interface ProgramSourceInfo { sourceInfo: SourceInfo[]; /** How the program counter offset is calculated * - none: The pc values in sourceInfo are not offset - * - cblocks: The pc values in sourceInfo are offset by PC of the last cblock at the top of the program + * - cblocks: The pc values in sourceInfo are offset by the PC of the first op following the last cblock at the top of the program */ pcOffsetMethod: "none" | "cblocks"; } @@ -360,7 +360,7 @@ intcblock 0x12345678 TMPL_BAR When a program has a template variable with a dynamic length, the `pcOffsetMethod` in `ProgramSourceInfo` **MUST** be `cblocks`. The `pc` value in each `SourceInfo` **MUST** be the pc determined at compilation minus the last `pc` value of the last `cblock` at compilation. -When a client is leveraging a source map with `cblocks` as the `pcOffsetMethod`, it **MUST** determine the `pc` value by parsing the bytecode to get the PC value of the last `cblock` at the top of the program. See the reference implementation section for an example of how to do this. +When a client is leveraging a source map with `cblocks` as the `pcOffsetMethod`, it **MUST** determine the `pc` value by parsing the bytecode to get the PC value of the first op following the last `cblock` at the top of the program. See the reference implementation section for an example of how to do this. ## Rationale From d58be413df4a686644f3d94084a0c07d8d61a06b Mon Sep 17 00:00:00 2001 From: Joe Polny <50534337+joe-p@users.noreply.github.com> Date: Wed, 16 Oct 2024 08:19:08 -0400 Subject: [PATCH 51/57] fix typo Co-authored-by: Daniel McGregor --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index eee7689b7..726602d3b 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -30,7 +30,7 @@ Every application is described via the following interface which is an extension ```ts /** Describes the entire contract. This interface is an extension of the interface described in ARC-4 */ interface Contract { - /** The ARCs used and/or supported by this contract. All contracts implicity support ARC4 and ARC56 */ + /** The ARCs used and/or supported by this contract. All contracts implicitly support ARC4 and ARC56 */ arcs: number[]; /** A user-friendly name for the contract */ name: string; From 9ba13f11909959f1aedc77a3c8d5df1e1ea69124 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 16 Oct 2024 08:32:20 -0400 Subject: [PATCH 52/57] remove ClearState --- ARCs/arc-0056.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 726602d3b..60f64f804 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -87,7 +87,6 @@ interface Contract { | "NoOp" | "OptIn" | "CloseOut" - | "ClearState" | "UpdateApplication" | "DeleteApplication" )[]; @@ -201,7 +200,6 @@ interface Method { | "NoOp" | "OptIn" | "CloseOut" - | "ClearState" | "UpdateApplication" | "DeleteApplication" )[]; From 20369ed9c82bc5aa00ae06985d4d24eb3f147861 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 16 Oct 2024 08:40:35 -0400 Subject: [PATCH 53/57] defaultValue fields --- ARCs/arc-0056.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 60f64f804..96f9c6bf0 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -168,10 +168,6 @@ interface Method { desc?: string; /** The default value that clients should use. */ defaultValue?: { - /** Base64 encoded bytes or uint64 */ - data: string | bigint; - /** How the data is encoded. This is the encoding for the data provided here, not the arg type */ - type: ABIType | AVMType; /** Where the default value is coming from * - box: The data key signifies the box key to read the value from * - global: The data key signifies the global state key to read the value from @@ -180,6 +176,10 @@ interface Method { * - method: The utf8 signature of the method in this contract to call to get the default value. If the method has arguments, they all must have default values. The method **MUST** be readonly so simulate can be used to get the default value. */ source: "box" | "global" | "local" | "literal" | "method"; + /** Base64 encoded bytes, base64 ARC4 encoded uint64, or UTF-8 method selector */ + data: string; + /** How the data is encoded. This is the encoding for the data provided here, not the arg type. Undefined if the data is method selector */ + type?: ABIType | AVMType; }; }>; /** Information about the method's return value */ From 027462f9ccf298a406c62252c323445ede9dc9ea Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 23 Oct 2024 05:32:23 -0400 Subject: [PATCH 54/57] make errorMessage optional, add optional teal and source to SourceInfo --- ARCs/arc-0056.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 96f9c6bf0..315aa4076 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -338,7 +338,11 @@ interface SourceInfo { /** The program counter value(s). Could be offset if pcOffsetMethod is not "none" */ pc: Array; /** A human-readable string that describes the error when the program fails at the given PC */ - errorMessage: string; + errorMessage?: string; + /** The TEAL line number that corresponds to the given PC. RECOMMENDED to be used for development purposes, but not required for clients */ + teal?: string; + /** The original source file and line number that corresponds to the given PC. RECOMMENDED to be used for development purposes, but not required for clients */ + source?: string; } ``` From 12e3a53184aa676706c57c5aebf0cc944c73c120 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 23 Oct 2024 06:49:08 -0400 Subject: [PATCH 55/57] teal string -> number --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 315aa4076..057d84e4f 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -340,7 +340,7 @@ interface SourceInfo { /** A human-readable string that describes the error when the program fails at the given PC */ errorMessage?: string; /** The TEAL line number that corresponds to the given PC. RECOMMENDED to be used for development purposes, but not required for clients */ - teal?: string; + teal?: number; /** The original source file and line number that corresponds to the given PC. RECOMMENDED to be used for development purposes, but not required for clients */ source?: string; } From 8e2db8d9b7c6856d890d306d7f7dc6d9feade0d1 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 23 Oct 2024 08:13:11 -0400 Subject: [PATCH 56/57] expand cblocks reference --- ARCs/arc-0056.md | 89 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 10 deletions(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 057d84e4f..68ecf61c7 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -392,35 +392,63 @@ NA ### Calculating cblock Offsets +Below is an example of how to determine the TEAL/source line for a PC from an algod error message when the `pcOffsetMethod` is `cblocks`. + ```ts +/** An ARC56 JSON file */ +import arc56Json from "./arc56.json"; + +/** The bytecblock opcode */ const BYTE_CBLOCK = 38; +/** The intcblock opcode */ const INT_CBLOCK = 32; -function parseConstantBlocks(bytes: number[]) { +/** + * Get the offset of the last constant block at the beginning of the program + * This value is used to calculate the program counter for an ARC56 program that has a pcOffsetMethod of "cblocks" + * + * @param program The program to parse + * @returns The PC value of the opcode after the last constant block + */ +function getConstantBlockOffset(program: Uint8Array) { + const bytes = [...program]; + const programSize = bytes.length; bytes.shift(); // remove version - const offsets: { bytecblock?: number; intcblock?: number; cblocks: number } = - { cblocks: 0 }; + + /** The PC of the opcode after the bytecblock */ + let bytecblockOffset: number | undefined; + + /** The PC of the opcode after the intcblock */ + let intcblockOffset: number | undefined; while (bytes.length > 0) { + /** The current byte from the beginning of the byte array */ const byte = bytes.shift()!; + // If the byte is a constant block... if (byte === BYTE_CBLOCK || byte === INT_CBLOCK) { const isBytecblock = byte === BYTE_CBLOCK; + + /** The byte following the opcode is the number of values in the constant block */ const valuesRemaining = bytes.shift()!; + // Iterate over all the values in the constant block for (let i = 0; i < valuesRemaining; i++) { if (isBytecblock) { - // byte is the length of the next element - bytes.splice(0, bytes.shift()!); + /** The byte following the opcode is the length of the next element */ + const length = bytes.shift()!; + bytes.splice(0, length); } else { // intcblock is a uvarint, so we need to keep reading until we find the end (MSB is not set) - while ((bytes.shift()! & 0x80) !== 0) {} + while ((bytes.shift()! & 0x80) !== 0) { + // Do nothing... + } } } - offsets[isBytecblock ? "bytecblock" : "intcblock"] = - programSize - bytes.length; + if (isBytecblock) bytecblockOffset = programSize - bytes.length - 1; + else intcblockOffset = programSize - bytes.length - 1; if (bytes[0] !== BYTE_CBLOCK && bytes[0] !== INT_CBLOCK) { // if the next opcode isn't a constant block, we're done @@ -429,8 +457,49 @@ function parseConstantBlocks(bytes: number[]) { } } - offsets.cblocks = Math.max(...Object.values(offsets)); - return offsets; + return Math.max(bytecblockOffset ?? 0, intcblockOffset ?? 0); +} + +/** The error message from algod */ +const algodError = + "Network request error. Received status 400 (Bad Request): TransactionPool.Remember: transaction ZR2LAFLRQYFZFV6WVKAPH6CANJMIBLLH5WRTSWT5CJHFVMF4UIFA: logic eval error: assert failed pc=162. Details: app=11927, pc=162, opcodes=log; intc_0 // 0; assert"; + +/** The PC of the error */ +const pc = Number(algodError.match(/pc=(\d+)/)![1]); + +// Parse the ARC56 JSON to determine if the PC values are offset by the constant blocks +if (arc56Json.sourceInfo.approval.pcOffsetMethod === "cblocks") { + /** The program can either be cached locally OR retried via the algod API */ + const program = new Uint8Array([ + 10, 32, 3, 0, 1, 6, 38, 3, 64, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 32, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 3, 102, 111, 111, 40, 41, 34, 42, + 49, 24, 20, 129, 6, 11, 49, 25, 8, 141, 12, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 0, 3, 129, 1, 67, 138, 0, + 0, 42, 176, 34, 68, 137, 136, 0, 3, 129, 1, 67, 138, 0, 0, 42, 40, 41, 132, + 137, 136, 0, 3, 129, 1, 67, 138, 0, 0, 0, 137, 128, 4, 21, 31, 124, 117, + 136, 0, 13, 73, 21, 22, 87, 6, 2, 76, 80, 80, 176, 129, 1, 67, 138, 0, 1, + 34, 22, 137, 129, 1, 67, 128, 4, 184, 68, 123, 54, 54, 26, 0, 142, 1, 255, + 240, 0, 128, 4, 154, 113, 210, 180, 128, 4, 223, 77, 92, 59, 128, 4, 61, + 135, 13, 135, 128, 4, 188, 11, 23, 6, 54, 26, 0, 142, 4, 255, 135, 255, 149, + 255, 163, 255, 174, 0, + ]); + + /** Get the offset of the last constant block */ + const offset = getConstantBlockOffset(program); + + /** Find the source info object that corresponds to the error's PC */ + const sourceInfoObject = arc56Json.sourceInfo.approval.sourceInfo.find((s) => + s.pc.includes(pc - offset) + )!; + + /** Get the TEAL line and source line that corresponds to the error */ + console.log( + `Error at PC ${pc} corresponds to TEAL line ${sourceInfoObject.teal} and source line ${sourceInfoObject.source}` + ); } ``` From 9a3f705660fa73520461550b226d9830b434b9f1 Mon Sep 17 00:00:00 2001 From: Joe Polny Date: Wed, 23 Oct 2024 08:18:44 -0400 Subject: [PATCH 57/57] fix typo --- ARCs/arc-0056.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCs/arc-0056.md b/ARCs/arc-0056.md index 68ecf61c7..05ae9edfb 100644 --- a/ARCs/arc-0056.md +++ b/ARCs/arc-0056.md @@ -469,7 +469,7 @@ const pc = Number(algodError.match(/pc=(\d+)/)![1]); // Parse the ARC56 JSON to determine if the PC values are offset by the constant blocks if (arc56Json.sourceInfo.approval.pcOffsetMethod === "cblocks") { - /** The program can either be cached locally OR retried via the algod API */ + /** The program can either be cached locally OR retrieved via the algod API */ const program = new Uint8Array([ 10, 32, 3, 0, 1, 6, 38, 3, 64, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,