From 59e176ef38b5a31bffa2656d0d7230b70861fa99 Mon Sep 17 00:00:00 2001 From: Tristan Menzel Date: Fri, 6 Dec 2024 15:03:53 -0800 Subject: [PATCH] feat: Reserved scratch space --- package.json | 2 +- src/awst/to-code-visitor.ts | 3 +- src/awst_build/eb/contract-builder.ts | 45 +- .../eb/literal-expression-builder.ts | 2 +- src/awst_build/models/contract-class-model.ts | 19 +- src/awst_build/models/decorator-data.ts | 3 +- src/util/intersect-sets.ts | 3 + .../ReserveScratchAlgo.approval.teal | 70 + .../ReserveScratchAlgo.clear.teal | 5 + .../reserve-scratch/ReserveScratchAlgo.ssa.ir | 37 + .../SubReserveScratchAlgo.approval.teal | 105 + .../SubReserveScratchAlgo.clear.teal | 5 + .../SubReserveScratchAlgo.ssa.ir | 49 + .../out/reserve-scratch/reserve-scratch.awst | 87 + .../reserve-scratch/reserve-scratch.awst.json | 2364 +++++++++++++++++ tests/approvals/reserve-scratch.algo.ts | 30 + 16 files changed, 2808 insertions(+), 21 deletions(-) create mode 100644 src/util/intersect-sets.ts create mode 100644 tests/approvals/out/reserve-scratch/ReserveScratchAlgo.approval.teal create mode 100644 tests/approvals/out/reserve-scratch/ReserveScratchAlgo.clear.teal create mode 100644 tests/approvals/out/reserve-scratch/ReserveScratchAlgo.ssa.ir create mode 100644 tests/approvals/out/reserve-scratch/SubReserveScratchAlgo.approval.teal create mode 100644 tests/approvals/out/reserve-scratch/SubReserveScratchAlgo.clear.teal create mode 100644 tests/approvals/out/reserve-scratch/SubReserveScratchAlgo.ssa.ir create mode 100644 tests/approvals/out/reserve-scratch/reserve-scratch.awst create mode 100644 tests/approvals/out/reserve-scratch/reserve-scratch.awst.json create mode 100644 tests/approvals/reserve-scratch.algo.ts diff --git a/package.json b/package.json index c6659fe0..ae4302a3 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "dev:examples": "tsx src/cli.ts build examples --output-awst --output-awst-json", "dev:approvals": "rimraf tests/approvals/out && tsx src/cli.ts build tests/approvals --dry-run", "dev:expected-output": "tsx src/cli.ts build tests/expected-output --dry-run", - "dev:testing": "tsx src/cli.ts build tests/approvals/state-totals.algo.ts --output-awst --output-awst-json --output-ssa-ir --log-level=info --out-dir out/[name] --optimization-level=0", + "dev:testing": "tsx src/cli.ts build tests/approvals/reserve-scratch.algo.ts --output-awst --output-awst-json --output-ssa-ir --log-level=info --out-dir out/[name] --optimization-level=0", "audit": "better-npm-audit audit", "format": "prettier --write .", "lint": "eslint \"src/**/*.ts\"", diff --git a/src/awst/to-code-visitor.ts b/src/awst/to-code-visitor.ts index c882e557..2c687d86 100644 --- a/src/awst/to-code-visitor.ts +++ b/src/awst/to-code-visitor.ts @@ -1,6 +1,5 @@ import { Buffer } from 'node:buffer' import { TodoError } from '../errors' -import { logger } from '../logger' import { uint8ArrayToBase32, uint8ArrayToUtf8 } from '../util' import type { ContractReference } from './models' import type { @@ -408,7 +407,7 @@ export class ToCodeVisitor } } if (c.reservedScratchSpace.size) { - logger.warn(c.sourceLocation, 'Handle reservedScratchSpace to-code') + body.push(`reservedScratchSpace: [${Array.from(c.reservedScratchSpace).join(', ')}]`) } if (c.approvalProgram) { body.push(...this.visitSpecialMethod(c.approvalProgram, 'approvalProgram')) diff --git a/src/awst_build/eb/contract-builder.ts b/src/awst_build/eb/contract-builder.ts index 953acff1..acecc7df 100644 --- a/src/awst_build/eb/contract-builder.ts +++ b/src/awst_build/eb/contract-builder.ts @@ -24,7 +24,9 @@ import { instanceEb } from '../type-registry' import { BaseContractMethodExpressionBuilder, ContractMethodExpressionBuilder } from './free-subroutine-expression-builder' import type { NodeBuilder } from './index' import { DecoratorDataBuilder, FunctionBuilder, InstanceBuilder } from './index' -import { requireIntegerConstant, requireStringConstant } from './util' +import { ArrayLiteralExpressionBuilder } from './literal/array-literal-expression-builder' +import { BigIntLiteralExpressionBuilder } from './literal/big-int-literal-expression-builder' +import { requireStringConstant } from './util' import { parseFunctionArgs } from './util/arg-parsing' import { requireAvmVersion } from './util/avm-version' import { VoidExpressionBuilder } from './void-expression-builder' @@ -127,7 +129,7 @@ export class ContractOptionsDecoratorBuilder extends FunctionBuilder { readonly ptype = contractOptionsDecorator call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { const { - args: [{ avmVersion, name, stateTotals }], + args: [{ avmVersion, name, stateTotals, scratchSlots }], } = parseFunctionArgs({ args, typeArgs, @@ -149,15 +151,52 @@ export class ContractOptionsDecoratorBuilder extends FunctionBuilder { avmVersion: avmVersion && requireAvmVersion(avmVersion), name: name && requireStringConstant(name).value, stateTotals: stateTotals && buildStateTotals(stateTotals), + scratchSlots: scratchSlots && processScratchRanges(scratchSlots), sourceLocation, }) } } +function getRangeProp(builder: NodeBuilder, name: string): bigint { + if (builder.hasProperty(name)) { + return getLiteralNumber(builder.memberAccess(name, builder.sourceLocation)) + } + throw new CodeError('Scratch slot reservations should be either a single slot or an object containing a from and to property', { + sourceLocation: builder.sourceLocation, + }) +} + +function getLiteralNumber(builder: NodeBuilder) { + codeInvariant(builder instanceof BigIntLiteralExpressionBuilder, 'Expected numeric literal', builder.sourceLocation) + return builder.value +} + +function processScratchRanges(builder: NodeBuilder): Set { + codeInvariant( + builder instanceof ArrayLiteralExpressionBuilder, + 'Scratch ranges should be specified in an array literal', + builder.sourceLocation, + ) + const slots = new Set() + for (const item of builder.getItemBuilders()) { + if (item.resolvableToPType(numberPType)) { + slots.add(getLiteralNumber(item)) + } else { + const from = getRangeProp(item, 'from') + const to = getRangeProp(item, 'to') + for (let i = from; i <= to; i++) { + slots.add(i) + } + } + } + + return slots +} + function buildStateTotals(builder: NodeBuilder): ContractOptionsDecoratorData['stateTotals'] { function tryGetProp(name: string): bigint | undefined { if (builder.hasProperty(name)) { - return requireIntegerConstant(builder.memberAccess(name, builder.sourceLocation)).value + return getLiteralNumber(builder.memberAccess(name, builder.sourceLocation)) } return undefined } diff --git a/src/awst_build/eb/literal-expression-builder.ts b/src/awst_build/eb/literal-expression-builder.ts index 3df240c8..13cfb05d 100644 --- a/src/awst_build/eb/literal-expression-builder.ts +++ b/src/awst_build/eb/literal-expression-builder.ts @@ -74,6 +74,6 @@ export abstract class LiteralExpressionBuilder extends InstanceBuilder { } hasProperty(_name: string): boolean { - this.throwInvalidExpression() + return false } } diff --git a/src/awst_build/models/contract-class-model.ts b/src/awst_build/models/contract-class-model.ts index 6da47461..a60dfa32 100644 --- a/src/awst_build/models/contract-class-model.ts +++ b/src/awst_build/models/contract-class-model.ts @@ -11,6 +11,7 @@ import { logger } from '../../logger' import type { Props } from '../../typescript-helpers' import { codeInvariant, invariant, isIn } from '../../util' import { CustomKeyMap } from '../../util/custom-key-map' +import { intersectSets } from '../../util/intersect-sets' import type { ContractClassPType } from '../ptypes' import type { ContractOptionsDecoratorData } from './decorator-data' import { LogicSigClassModel } from './logic-sig-class-model' @@ -58,14 +59,18 @@ export class ContractClassModel { let clearProgram: ContractMethod | null = this.clearProgram const methods: ContractMethod[] = [...this.methods, this.ctor] const methodResolutionOrder: ContractReference[] = [] - let firstBaseWithStateTotals: ContractClassModel | undefined = undefined + let reservedScratchSpace = new Set() + for (const baseType of this.type.allBases()) { const cref = ContractReference.fromPType(baseType) const baseClass = compilationSet.getContractClass(cref) if (baseClass.hasExplicitStateTotals() && firstBaseWithStateTotals === undefined) { firstBaseWithStateTotals = baseClass } + if (baseClass.options?.scratchSlots) { + reservedScratchSpace = intersectSets(reservedScratchSpace, baseClass.options.scratchSlots) + } methodResolutionOrder.push(cref) approvalProgram ??= baseClass.approvalProgram clearProgram ??= baseClass.clearProgram @@ -114,18 +119,8 @@ export class ContractClassModel { localUints: this.options?.stateTotals?.localUints ?? null, }) - // TODO: Tally from bases - const reservedScratchSpace = new Set() if (this.options?.scratchSlots) { - for (const reservation of this.options.scratchSlots) { - if (typeof reservation === 'bigint') { - reservedScratchSpace.add(reservation) - } else { - for (let i = reservation.from; i <= reservation.to; i++) { - reservedScratchSpace.add(i) - } - } - } + reservedScratchSpace = intersectSets(reservedScratchSpace, this.options.scratchSlots) } return nodeFactory.contract({ diff --git a/src/awst_build/models/decorator-data.ts b/src/awst_build/models/decorator-data.ts index e796794c..0f4309bb 100644 --- a/src/awst_build/models/decorator-data.ts +++ b/src/awst_build/models/decorator-data.ts @@ -35,13 +35,12 @@ export type LogicSigOptionsDecoratorData = { avmVersion?: SupportedAvmVersion name?: string } -type NumberRange = { from: bigint; to: bigint } export type ContractOptionsDecoratorData = { type: typeof Constants.contractOptionsDecoratorName sourceLocation: SourceLocation avmVersion?: SupportedAvmVersion name?: string - scratchSlots?: Array + scratchSlots?: Set stateTotals?: { globalUints?: bigint globalBytes?: bigint diff --git a/src/util/intersect-sets.ts b/src/util/intersect-sets.ts new file mode 100644 index 00000000..fae364e0 --- /dev/null +++ b/src/util/intersect-sets.ts @@ -0,0 +1,3 @@ +export function intersectSets(...sets: Set[]): Set { + return new Set(sets.flatMap((s) => [...s])) +} diff --git a/tests/approvals/out/reserve-scratch/ReserveScratchAlgo.approval.teal b/tests/approvals/out/reserve-scratch/ReserveScratchAlgo.approval.teal new file mode 100644 index 00000000..98ed9f36 --- /dev/null +++ b/tests/approvals/out/reserve-scratch/ReserveScratchAlgo.approval.teal @@ -0,0 +1,70 @@ +#pragma version 10 + +tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.approvalProgram: + intcblock 1 0 15 45 + bytecblock "hello" + txn ApplicationID + bnz main_after_if_else@2 + callsub constructor + +main_after_if_else@2: + // tests/approvals/reserve-scratch.algo.ts:13 + // this.setThings() + callsub setThings + // tests/approvals/reserve-scratch.algo.ts:15 + // assert(Scratch.loadUint64(0) === 1) + intc_1 // 0 + loads + intc_0 // 1 + == + assert + // tests/approvals/reserve-scratch.algo.ts:16 + // assert(Scratch.loadBytes(0) === Bytes('hello')) + intc_1 // 0 + loads + bytec_0 // "hello" + == + assert + // tests/approvals/reserve-scratch.algo.ts:17 + // assert(Scratch.loadUint64(15) === 45) + intc_2 // 15 + loads + intc_3 // 45 + == + assert + // tests/approvals/reserve-scratch.algo.ts:18 + // return true + intc_0 // 1 + return + + +// tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.constructor() -> void: +constructor: + // tests/approvals/reserve-scratch.algo.ts:4-5 + // @contract({ scratchSlots: [0, 1, { from: 10, to: 20 }] }) + // export class ReserveScratchAlgo extends BaseContract { + proto 0 0 + retsub + + +// tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.setThings() -> void: +setThings: + // tests/approvals/reserve-scratch.algo.ts:6 + // setThings() { + proto 0 0 + // tests/approvals/reserve-scratch.algo.ts:7 + // Scratch.store(0, 1) + intc_1 // 0 + intc_0 // 1 + stores + // tests/approvals/reserve-scratch.algo.ts:8 + // Scratch.store(1, Bytes('hello')) + intc_0 // 1 + bytec_0 // "hello" + stores + // tests/approvals/reserve-scratch.algo.ts:9 + // Scratch.store(15, 45) + intc_2 // 15 + intc_3 // 45 + stores + retsub diff --git a/tests/approvals/out/reserve-scratch/ReserveScratchAlgo.clear.teal b/tests/approvals/out/reserve-scratch/ReserveScratchAlgo.clear.teal new file mode 100644 index 00000000..a73a2abc --- /dev/null +++ b/tests/approvals/out/reserve-scratch/ReserveScratchAlgo.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.clearStateProgram: + pushint 1 // 1 + return diff --git a/tests/approvals/out/reserve-scratch/ReserveScratchAlgo.ssa.ir b/tests/approvals/out/reserve-scratch/ReserveScratchAlgo.ssa.ir new file mode 100644 index 00000000..775720ce --- /dev/null +++ b/tests/approvals/out/reserve-scratch/ReserveScratchAlgo.ssa.ir @@ -0,0 +1,37 @@ +contract tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo: + program approval: + subroutine tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.approvalProgram() -> bool: + block@0: // L12 + let reinterpret_bool%0#0: bool = (txn ApplicationID) + goto reinterpret_bool%0#0 ? block@2 : block@1 + block@1: // if_body_L1 + tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.constructor() + goto block@2 + block@2: // after_if_else_L1 + tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.setThings() + let tmp%0#0: uint64 = (loads 0u) + let tmp%1#0: bool = (== tmp%0#0 1u) + (assert tmp%1#0) + let tmp%2#0: bytes = (loads 0u) + let tmp%3#0: bool = (== tmp%2#0 "hello") + (assert tmp%3#0) + let tmp%4#0: uint64 = (loads 15u) + let tmp%5#0: bool = (== tmp%4#0 45u) + (assert tmp%5#0) + return 1u + + subroutine tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.constructor() -> void: + block@0: // L4 + return + + subroutine tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.setThings() -> void: + block@0: // L6 + (stores 0u 1u) + (stores 1u "hello") + (stores 15u 45u) + return + + program clear-state: + subroutine @algorandfoundation/algorand-typescript/base-contract.d.ts::BaseContract.clearStateProgram() -> bool: + block@0: // L1 + return 1u \ No newline at end of file diff --git a/tests/approvals/out/reserve-scratch/SubReserveScratchAlgo.approval.teal b/tests/approvals/out/reserve-scratch/SubReserveScratchAlgo.approval.teal new file mode 100644 index 00000000..6ee7cb73 --- /dev/null +++ b/tests/approvals/out/reserve-scratch/SubReserveScratchAlgo.approval.teal @@ -0,0 +1,105 @@ +#pragma version 10 + +tests/approvals/reserve-scratch.algo.ts::SubReserveScratchAlgo.approvalProgram: + intcblock 1 0 15 45 + bytecblock "world" "hello" + txn ApplicationID + bnz main_after_if_else@2 + callsub constructor + +main_after_if_else@2: + // tests/approvals/reserve-scratch.algo.ts:25 + // super.approvalProgram() + callsub approvalProgram + pop + // tests/approvals/reserve-scratch.algo.ts:26 + // Scratch.store(50, Bytes('world')) + pushint 50 // 50 + bytec_0 // "world" + stores + // tests/approvals/reserve-scratch.algo.ts:27 + // Scratch.store(16, Bytes('world')) + pushint 16 // 16 + bytec_0 // "world" + stores + // tests/approvals/reserve-scratch.algo.ts:28 + // return true + intc_0 // 1 + return + + +// tests/approvals/reserve-scratch.algo.ts::SubReserveScratchAlgo.constructor() -> void: +constructor: + // tests/approvals/reserve-scratch.algo.ts:22-23 + // @contract({ scratchSlots: [50] }) + // export class SubReserveScratchAlgo extends ReserveScratchAlgo { + proto 0 0 + callsub tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.constructor + retsub + + +// tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.constructor() -> void: +tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.constructor: + // tests/approvals/reserve-scratch.algo.ts:4-5 + // @contract({ scratchSlots: [0, 1, { from: 10, to: 20 }] }) + // export class ReserveScratchAlgo extends BaseContract { + proto 0 0 + retsub + + +// tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.approvalProgram() -> uint64: +approvalProgram: + // tests/approvals/reserve-scratch.algo.ts:12 + // approvalProgram(): boolean { + proto 0 1 + // tests/approvals/reserve-scratch.algo.ts:13 + // this.setThings() + callsub setThings + // tests/approvals/reserve-scratch.algo.ts:15 + // assert(Scratch.loadUint64(0) === 1) + intc_1 // 0 + loads + intc_0 // 1 + == + assert + // tests/approvals/reserve-scratch.algo.ts:16 + // assert(Scratch.loadBytes(0) === Bytes('hello')) + intc_1 // 0 + loads + bytec_1 // "hello" + == + assert + // tests/approvals/reserve-scratch.algo.ts:17 + // assert(Scratch.loadUint64(15) === 45) + intc_2 // 15 + loads + intc_3 // 45 + == + assert + // tests/approvals/reserve-scratch.algo.ts:18 + // return true + intc_0 // 1 + retsub + + +// tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.setThings() -> void: +setThings: + // tests/approvals/reserve-scratch.algo.ts:6 + // setThings() { + proto 0 0 + // tests/approvals/reserve-scratch.algo.ts:7 + // Scratch.store(0, 1) + intc_1 // 0 + intc_0 // 1 + stores + // tests/approvals/reserve-scratch.algo.ts:8 + // Scratch.store(1, Bytes('hello')) + intc_0 // 1 + bytec_1 // "hello" + stores + // tests/approvals/reserve-scratch.algo.ts:9 + // Scratch.store(15, 45) + intc_2 // 15 + intc_3 // 45 + stores + retsub diff --git a/tests/approvals/out/reserve-scratch/SubReserveScratchAlgo.clear.teal b/tests/approvals/out/reserve-scratch/SubReserveScratchAlgo.clear.teal new file mode 100644 index 00000000..e5a0b635 --- /dev/null +++ b/tests/approvals/out/reserve-scratch/SubReserveScratchAlgo.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +tests/approvals/reserve-scratch.algo.ts::SubReserveScratchAlgo.clearStateProgram: + pushint 1 // 1 + return diff --git a/tests/approvals/out/reserve-scratch/SubReserveScratchAlgo.ssa.ir b/tests/approvals/out/reserve-scratch/SubReserveScratchAlgo.ssa.ir new file mode 100644 index 00000000..9d4420f3 --- /dev/null +++ b/tests/approvals/out/reserve-scratch/SubReserveScratchAlgo.ssa.ir @@ -0,0 +1,49 @@ +contract tests/approvals/reserve-scratch.algo.ts::SubReserveScratchAlgo: + program approval: + subroutine tests/approvals/reserve-scratch.algo.ts::SubReserveScratchAlgo.approvalProgram() -> bool: + block@0: // L24 + let reinterpret_bool%0#0: bool = (txn ApplicationID) + goto reinterpret_bool%0#0 ? block@2 : block@1 + block@1: // if_body_L1 + tests/approvals/reserve-scratch.algo.ts::SubReserveScratchAlgo.constructor() + goto block@2 + block@2: // after_if_else_L1 + tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.approvalProgram() + (stores 50u "world") + (stores 16u "world") + return 1u + + subroutine tests/approvals/reserve-scratch.algo.ts::SubReserveScratchAlgo.constructor() -> void: + block@0: // L22 + tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.constructor() + return + + subroutine tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.constructor() -> void: + block@0: // L4 + return + + subroutine tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.approvalProgram() -> bool: + block@0: // L12 + tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.setThings() + let tmp%0#0: uint64 = (loads 0u) + let tmp%1#0: bool = (== tmp%0#0 1u) + (assert tmp%1#0) + let tmp%2#0: bytes = (loads 0u) + let tmp%3#0: bool = (== tmp%2#0 "hello") + (assert tmp%3#0) + let tmp%4#0: uint64 = (loads 15u) + let tmp%5#0: bool = (== tmp%4#0 45u) + (assert tmp%5#0) + return 1u + + subroutine tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo.setThings() -> void: + block@0: // L6 + (stores 0u 1u) + (stores 1u "hello") + (stores 15u 45u) + return + + program clear-state: + subroutine @algorandfoundation/algorand-typescript/base-contract.d.ts::BaseContract.clearStateProgram() -> bool: + block@0: // L1 + return 1u \ No newline at end of file diff --git a/tests/approvals/out/reserve-scratch/reserve-scratch.awst b/tests/approvals/out/reserve-scratch/reserve-scratch.awst new file mode 100644 index 00000000..8c51e675 --- /dev/null +++ b/tests/approvals/out/reserve-scratch/reserve-scratch.awst @@ -0,0 +1,87 @@ +contract ReserveScratchAlgo +{ + reservedScratchSpace: [0, 1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] + approvalProgram(): bool + { + if (!Boolean(txn())) { + this.constructor() + } + this.setThings() + assert(loads(0) == 1) + assert(loads(0) == "hello") + assert(loads(15) == 45) + return True + } + + clearProgram(): bool + { + return True + } + + setThings(): void + { + stores(0, 1) + stores(1, "hello") + stores(15, 45) + } + + constructor(): void + { + void + } + + BaseContract::constructor(): void + { + } + +} +contract SubReserveScratchAlgo +{ + reservedScratchSpace: [0, 1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 50] + approvalProgram(): bool + { + if (!Boolean(txn())) { + this.constructor() + } + super.approvalProgram() + stores(50, "world") + stores(16, "world") + return True + } + + clearProgram(): bool + { + return True + } + + constructor(): void + { + super.constructor() + } + + ReserveScratchAlgo::approvalProgram(): bool + { + this.setThings() + assert(loads(0) == 1) + assert(loads(0) == "hello") + assert(loads(15) == 45) + return True + } + + ReserveScratchAlgo::setThings(): void + { + stores(0, 1) + stores(1, "hello") + stores(15, 45) + } + + ReserveScratchAlgo::constructor(): void + { + void + } + + BaseContract::constructor(): void + { + } + +} \ No newline at end of file diff --git a/tests/approvals/out/reserve-scratch/reserve-scratch.awst.json b/tests/approvals/out/reserve-scratch/reserve-scratch.awst.json new file mode 100644 index 00000000..d7c72f07 --- /dev/null +++ b/tests/approvals/out/reserve-scratch/reserve-scratch.awst.json @@ -0,0 +1,2364 @@ +[ + { + "_type": "Contract", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 4, + "end_line": 5, + "column": 0, + "end_column": 54 + }, + "id": "tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo", + "name": "ReserveScratchAlgo", + "description": null, + "method_resolution_order": [ + "@algorandfoundation/algorand-typescript/base-contract.d.ts::BaseContract" + ], + "approval_program": { + "_type": "ContractMethod", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 12, + "end_line": 12, + "column": 2, + "end_column": 28 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "body": { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [ + { + "_type": "IfElse", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "condition": { + "_type": "Not", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "expr": { + "_type": "ReinterpretCast", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "op_code": "txn", + "immediates": [ + "ApplicationID" + ], + "stack_args": [] + } + } + }, + "if_branch": { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "expr": { + "_type": "SubroutineCallExpression", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "target": { + "_type": "InstanceMethodTarget", + "member_name": "constructor" + }, + "args": [] + } + } + ], + "label": null, + "comment": null + }, + "else_branch": null + }, + { + "_type": "Block", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 12, + "end_line": 19, + "column": 29, + "end_column": 3 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 13, + "end_line": 13, + "column": 4, + "end_column": 20 + }, + "expr": { + "_type": "SubroutineCallExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 13, + "end_line": 13, + "column": 4, + "end_column": 20 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "target": { + "_type": "InstanceMethodTarget", + "member_name": "setThings" + }, + "args": [] + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 15, + "end_line": 15, + "column": 4, + "end_column": 39 + }, + "expr": { + "_type": "AssertExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 15, + "end_line": 15, + "column": 4, + "end_column": 39 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "condition": { + "_type": "NumericComparisonExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 15, + "end_line": 15, + "column": 11, + "end_column": 38 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "lhs": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 15, + "end_line": 15, + "column": 11, + "end_column": 32 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "op_code": "loads", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 15, + "end_line": 15, + "column": 30, + "end_column": 31 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "0", + "teal_alias": null + } + ] + }, + "operator": "==", + "rhs": { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 15, + "end_line": 15, + "column": 37, + "end_column": 38 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "1", + "teal_alias": null + } + }, + "error_message": null + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 16, + "end_line": 16, + "column": 4, + "end_column": 51 + }, + "expr": { + "_type": "AssertExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 16, + "end_line": 16, + "column": 4, + "end_column": 51 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "condition": { + "_type": "BytesComparisonExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 16, + "end_line": 16, + "column": 11, + "end_column": 50 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "lhs": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 16, + "end_line": 16, + "column": 11, + "end_column": 31 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "op_code": "loads", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 16, + "end_line": 16, + "column": 29, + "end_column": 30 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "0", + "teal_alias": null + } + ] + }, + "operator": "==", + "rhs": { + "_type": "BytesConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 16, + "end_line": 16, + "column": 42, + "end_column": 49 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "value": "Xk~0{Zv", + "encoding": "utf8" + } + }, + "error_message": null + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 17, + "end_line": 17, + "column": 4, + "end_column": 41 + }, + "expr": { + "_type": "AssertExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 17, + "end_line": 17, + "column": 4, + "end_column": 41 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "condition": { + "_type": "NumericComparisonExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 17, + "end_line": 17, + "column": 11, + "end_column": 40 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "lhs": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 17, + "end_line": 17, + "column": 11, + "end_column": 33 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "op_code": "loads", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 17, + "end_line": 17, + "column": 30, + "end_column": 32 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "15", + "teal_alias": null + } + ] + }, + "operator": "==", + "rhs": { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 17, + "end_line": 17, + "column": 38, + "end_column": 40 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "45", + "teal_alias": null + } + }, + "error_message": null + } + }, + { + "_type": "ReturnStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 18, + "end_line": 18, + "column": 4, + "end_column": 15 + }, + "value": { + "_type": "BoolConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 18, + "end_line": 18, + "column": 11, + "end_column": 15 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": true + } + } + ], + "label": null, + "comment": null + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo", + "member_name": "approvalProgram", + "arc4_method_config": null + }, + "clear_program": { + "_type": "ContractMethod", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "body": { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [ + { + "_type": "ReturnStatement", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "value": { + "_type": "BoolConstant", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": true + } + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "@algorandfoundation/algorand-typescript/base-contract.d.ts::BaseContract", + "member_name": "clearStateProgram", + "arc4_method_config": null + }, + "methods": [ + { + "_type": "ContractMethod", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 6, + "end_line": 6, + "column": 2, + "end_column": 13 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "body": { + "_type": "Block", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 6, + "end_line": 10, + "column": 14, + "end_column": 3 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 7, + "end_line": 7, + "column": 4, + "end_column": 23 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 7, + "end_line": 7, + "column": 4, + "end_column": 23 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "op_code": "stores", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 7, + "end_line": 7, + "column": 18, + "end_column": 19 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "0", + "teal_alias": null + }, + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 7, + "end_line": 7, + "column": 21, + "end_column": 22 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "1", + "teal_alias": null + } + ] + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 8, + "end_line": 8, + "column": 4, + "end_column": 36 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 8, + "end_line": 8, + "column": 4, + "end_column": 36 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "op_code": "stores", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 8, + "end_line": 8, + "column": 18, + "end_column": 19 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "1", + "teal_alias": null + }, + { + "_type": "BytesConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 8, + "end_line": 8, + "column": 27, + "end_column": 34 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "value": "Xk~0{Zv", + "encoding": "utf8" + } + ] + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 9, + "end_line": 9, + "column": 4, + "end_column": 25 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 9, + "end_line": 9, + "column": 4, + "end_column": 25 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "op_code": "stores", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 9, + "end_line": 9, + "column": 18, + "end_column": 20 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "15", + "teal_alias": null + }, + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 9, + "end_line": 9, + "column": 22, + "end_column": 24 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "45", + "teal_alias": null + } + ] + } + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo", + "member_name": "setThings", + "arc4_method_config": null + }, + { + "_type": "ContractMethod", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 4, + "end_line": 5, + "column": 0, + "end_column": 54 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "body": { + "_type": "Block", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 4, + "end_line": 5, + "column": 0, + "end_column": 54 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 4, + "end_line": 5, + "column": 0, + "end_column": 54 + }, + "expr": { + "_type": "VoidConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 4, + "end_line": 5, + "column": 0, + "end_column": 54 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + } + } + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo", + "member_name": "constructor", + "arc4_method_config": null + }, + { + "_type": "ContractMethod", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "body": { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "@algorandfoundation/algorand-typescript/base-contract.d.ts::BaseContract", + "member_name": "constructor", + "arc4_method_config": null + } + ], + "app_state": [], + "state_totals": { + "_type": "StateTotals", + "global_uints": null, + "local_uints": null, + "global_bytes": null, + "local_bytes": null + }, + "reserved_scratch_space": [ + "0", + "1", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "20" + ], + "avm_version": null + }, + { + "_type": "Contract", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 22, + "end_line": 23, + "column": 0, + "end_column": 63 + }, + "id": "tests/approvals/reserve-scratch.algo.ts::SubReserveScratchAlgo", + "name": "SubReserveScratchAlgo", + "description": null, + "method_resolution_order": [ + "tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo", + "@algorandfoundation/algorand-typescript/base-contract.d.ts::BaseContract" + ], + "approval_program": { + "_type": "ContractMethod", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 24, + "end_line": 24, + "column": 2, + "end_column": 28 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "body": { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [ + { + "_type": "IfElse", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "condition": { + "_type": "Not", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "expr": { + "_type": "ReinterpretCast", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "op_code": "txn", + "immediates": [ + "ApplicationID" + ], + "stack_args": [] + } + } + }, + "if_branch": { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "expr": { + "_type": "SubroutineCallExpression", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "target": { + "_type": "InstanceMethodTarget", + "member_name": "constructor" + }, + "args": [] + } + } + ], + "label": null, + "comment": null + }, + "else_branch": null + }, + { + "_type": "Block", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 24, + "end_line": 29, + "column": 29, + "end_column": 3 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 25, + "end_line": 25, + "column": 4, + "end_column": 27 + }, + "expr": { + "_type": "SubroutineCallExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 25, + "end_line": 25, + "column": 4, + "end_column": 27 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "target": { + "_type": "InstanceSuperMethodTarget", + "member_name": "approvalProgram" + }, + "args": [] + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 26, + "end_line": 26, + "column": 4, + "end_column": 37 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 26, + "end_line": 26, + "column": 4, + "end_column": 37 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "op_code": "stores", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 26, + "end_line": 26, + "column": 18, + "end_column": 20 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "50", + "teal_alias": null + }, + { + "_type": "BytesConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 26, + "end_line": 26, + "column": 28, + "end_column": 35 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "value": "cW-iRWB", + "encoding": "utf8" + } + ] + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 27, + "end_line": 27, + "column": 4, + "end_column": 37 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 27, + "end_line": 27, + "column": 4, + "end_column": 37 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "op_code": "stores", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 27, + "end_line": 27, + "column": 18, + "end_column": 20 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "16", + "teal_alias": null + }, + { + "_type": "BytesConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 27, + "end_line": 27, + "column": 28, + "end_column": 35 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "value": "cW-iRWB", + "encoding": "utf8" + } + ] + } + }, + { + "_type": "ReturnStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 28, + "end_line": 28, + "column": 4, + "end_column": 15 + }, + "value": { + "_type": "BoolConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 28, + "end_line": 28, + "column": 11, + "end_column": 15 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": true + } + } + ], + "label": null, + "comment": null + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "tests/approvals/reserve-scratch.algo.ts::SubReserveScratchAlgo", + "member_name": "approvalProgram", + "arc4_method_config": null + }, + "clear_program": { + "_type": "ContractMethod", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "body": { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [ + { + "_type": "ReturnStatement", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "value": { + "_type": "BoolConstant", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": true + } + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "@algorandfoundation/algorand-typescript/base-contract.d.ts::BaseContract", + "member_name": "clearStateProgram", + "arc4_method_config": null + }, + "methods": [ + { + "_type": "ContractMethod", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 22, + "end_line": 23, + "column": 0, + "end_column": 63 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "body": { + "_type": "Block", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 22, + "end_line": 23, + "column": 0, + "end_column": 63 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 22, + "end_line": 23, + "column": 0, + "end_column": 63 + }, + "expr": { + "_type": "SubroutineCallExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 22, + "end_line": 23, + "column": 0, + "end_column": 63 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "target": { + "_type": "InstanceSuperMethodTarget", + "member_name": "constructor" + }, + "args": [] + } + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "tests/approvals/reserve-scratch.algo.ts::SubReserveScratchAlgo", + "member_name": "constructor", + "arc4_method_config": null + }, + { + "_type": "ContractMethod", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 12, + "end_line": 12, + "column": 2, + "end_column": 28 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "body": { + "_type": "Block", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 12, + "end_line": 19, + "column": 29, + "end_column": 3 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 13, + "end_line": 13, + "column": 4, + "end_column": 20 + }, + "expr": { + "_type": "SubroutineCallExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 13, + "end_line": 13, + "column": 4, + "end_column": 20 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "target": { + "_type": "InstanceMethodTarget", + "member_name": "setThings" + }, + "args": [] + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 15, + "end_line": 15, + "column": 4, + "end_column": 39 + }, + "expr": { + "_type": "AssertExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 15, + "end_line": 15, + "column": 4, + "end_column": 39 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "condition": { + "_type": "NumericComparisonExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 15, + "end_line": 15, + "column": 11, + "end_column": 38 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "lhs": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 15, + "end_line": 15, + "column": 11, + "end_column": 32 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "op_code": "loads", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 15, + "end_line": 15, + "column": 30, + "end_column": 31 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "0", + "teal_alias": null + } + ] + }, + "operator": "==", + "rhs": { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 15, + "end_line": 15, + "column": 37, + "end_column": 38 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "1", + "teal_alias": null + } + }, + "error_message": null + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 16, + "end_line": 16, + "column": 4, + "end_column": 51 + }, + "expr": { + "_type": "AssertExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 16, + "end_line": 16, + "column": 4, + "end_column": 51 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "condition": { + "_type": "BytesComparisonExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 16, + "end_line": 16, + "column": 11, + "end_column": 50 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "lhs": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 16, + "end_line": 16, + "column": 11, + "end_column": 31 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "op_code": "loads", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 16, + "end_line": 16, + "column": 29, + "end_column": 30 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "0", + "teal_alias": null + } + ] + }, + "operator": "==", + "rhs": { + "_type": "BytesConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 16, + "end_line": 16, + "column": 42, + "end_column": 49 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "value": "Xk~0{Zv", + "encoding": "utf8" + } + }, + "error_message": null + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 17, + "end_line": 17, + "column": 4, + "end_column": 41 + }, + "expr": { + "_type": "AssertExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 17, + "end_line": 17, + "column": 4, + "end_column": 41 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "condition": { + "_type": "NumericComparisonExpression", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 17, + "end_line": 17, + "column": 11, + "end_column": 40 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "lhs": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 17, + "end_line": 17, + "column": 11, + "end_column": 33 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "op_code": "loads", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 17, + "end_line": 17, + "column": 30, + "end_column": 32 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "15", + "teal_alias": null + } + ] + }, + "operator": "==", + "rhs": { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 17, + "end_line": 17, + "column": 38, + "end_column": 40 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "45", + "teal_alias": null + } + }, + "error_message": null + } + }, + { + "_type": "ReturnStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 18, + "end_line": 18, + "column": 4, + "end_column": 15 + }, + "value": { + "_type": "BoolConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 18, + "end_line": 18, + "column": 11, + "end_column": 15 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": true + } + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo", + "member_name": "approvalProgram", + "arc4_method_config": null + }, + { + "_type": "ContractMethod", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 6, + "end_line": 6, + "column": 2, + "end_column": 13 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "body": { + "_type": "Block", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 6, + "end_line": 10, + "column": 14, + "end_column": 3 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 7, + "end_line": 7, + "column": 4, + "end_column": 23 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 7, + "end_line": 7, + "column": 4, + "end_column": 23 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "op_code": "stores", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 7, + "end_line": 7, + "column": 18, + "end_column": 19 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "0", + "teal_alias": null + }, + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 7, + "end_line": 7, + "column": 21, + "end_column": 22 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "1", + "teal_alias": null + } + ] + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 8, + "end_line": 8, + "column": 4, + "end_column": 36 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 8, + "end_line": 8, + "column": 4, + "end_column": 36 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "op_code": "stores", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 8, + "end_line": 8, + "column": 18, + "end_column": 19 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "1", + "teal_alias": null + }, + { + "_type": "BytesConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 8, + "end_line": 8, + "column": 27, + "end_column": 34 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "value": "Xk~0{Zv", + "encoding": "utf8" + } + ] + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 9, + "end_line": 9, + "column": 4, + "end_column": 25 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 9, + "end_line": 9, + "column": 4, + "end_column": 25 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "op_code": "stores", + "immediates": [], + "stack_args": [ + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 9, + "end_line": 9, + "column": 18, + "end_column": 20 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "15", + "teal_alias": null + }, + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 9, + "end_line": 9, + "column": 22, + "end_column": 24 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "45", + "teal_alias": null + } + ] + } + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo", + "member_name": "setThings", + "arc4_method_config": null + }, + { + "_type": "ContractMethod", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 4, + "end_line": 5, + "column": 0, + "end_column": 54 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "body": { + "_type": "Block", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 4, + "end_line": 5, + "column": 0, + "end_column": 54 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 4, + "end_line": 5, + "column": 0, + "end_column": 54 + }, + "expr": { + "_type": "VoidConstant", + "source_location": { + "file": "tests/approvals/reserve-scratch.algo.ts", + "line": 4, + "end_line": 5, + "column": 0, + "end_column": 54 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + } + } + } + ], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "tests/approvals/reserve-scratch.algo.ts::ReserveScratchAlgo", + "member_name": "constructor", + "arc4_method_config": null + }, + { + "_type": "ContractMethod", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "args": [], + "return_type": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "body": { + "_type": "Block", + "source_location": { + "_type": "SourceLocation", + "file": null, + "line": 1, + "end_line": 1, + "column": 0, + "end_column": 1 + }, + "body": [], + "label": null, + "comment": null + }, + "documentation": { + "_type": "MethodDocumentation", + "description": null, + "args": {}, + "returns": null + }, + "cref": "@algorandfoundation/algorand-typescript/base-contract.d.ts::BaseContract", + "member_name": "constructor", + "arc4_method_config": null + } + ], + "app_state": [], + "state_totals": { + "_type": "StateTotals", + "global_uints": null, + "local_uints": null, + "global_bytes": null, + "local_bytes": null + }, + "reserved_scratch_space": [ + "0", + "1", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "20", + "50" + ], + "avm_version": null + } +] \ No newline at end of file diff --git a/tests/approvals/reserve-scratch.algo.ts b/tests/approvals/reserve-scratch.algo.ts new file mode 100644 index 00000000..cd209de2 --- /dev/null +++ b/tests/approvals/reserve-scratch.algo.ts @@ -0,0 +1,30 @@ +import { assert, BaseContract, Bytes, contract } from '@algorandfoundation/algorand-typescript' +import { Scratch } from '@algorandfoundation/algorand-typescript/op' + +@contract({ scratchSlots: [0, 1, { from: 10, to: 20 }] }) +export class ReserveScratchAlgo extends BaseContract { + setThings() { + Scratch.store(0, 1) + Scratch.store(1, Bytes('hello')) + Scratch.store(15, 45) + } + + approvalProgram(): boolean { + this.setThings() + + assert(Scratch.loadUint64(0) === 1) + assert(Scratch.loadBytes(0) === Bytes('hello')) + assert(Scratch.loadUint64(15) === 45) + return true + } +} + +@contract({ scratchSlots: [50] }) +export class SubReserveScratchAlgo extends ReserveScratchAlgo { + approvalProgram(): boolean { + super.approvalProgram() + Scratch.store(50, Bytes('world')) + Scratch.store(16, Bytes('world')) + return true + } +}