Skip to content

Commit

Permalink
feat: Allow stateTotals to be specified statically in contract options
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanmenzel committed Dec 6, 2024
1 parent 56725d2 commit 52ebc65
Show file tree
Hide file tree
Showing 29 changed files with 4,554 additions and 25 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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/avm11.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/state-totals.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\"",
Expand Down
4 changes: 2 additions & 2 deletions packages/algo-ts/src/base-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ type ContractOptions = {
* Allows defining what values should be used for global and local uint and bytes storage
* values when creating a contract. Used when outputting ARC-32 application.json schemas.
*
* If let unspecified, the totals will be determined by the compiler based on state
* If left unspecified, the totals will be determined by the compiler based on state
* variables assigned to `this`.
*
* This setting is not inherited, and only applies to the exact `Contract` it is specified
* on. If a base class does specify this setting, and a derived class does not, a warning
* will be emitted for the derived class. To resolve this warning, `state_totals` must be
* will be emitted for the derived class. To resolve this warning, `stateTotals` must be
* specified. An empty object may be provided in order to indicate that this contract should
* revert to the default behaviour
*/
Expand Down
26 changes: 22 additions & 4 deletions src/awst_build/eb/contract-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Constants } from '../../constants'
import { CodeError } from '../../errors'
import { codeInvariant, invariant } from '../../util'
import type { AwstBuildContext } from '../context/awst-build-context'
import type { ContractOptionsDecoratorData } from '../models/decorator-data'
import type { PType } from '../ptypes'
import {
arc4BaseContractType,
Expand All @@ -23,7 +24,7 @@ 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 { requireStringConstant } from './util'
import { requireIntegerConstant, requireStringConstant } from './util'
import { parseFunctionArgs } from './util/arg-parsing'
import { requireAvmVersion } from './util/avm-version'
import { VoidExpressionBuilder } from './void-expression-builder'
Expand Down Expand Up @@ -126,7 +127,7 @@ export class ContractOptionsDecoratorBuilder extends FunctionBuilder {
readonly ptype = contractOptionsDecorator
call(args: ReadonlyArray<NodeBuilder>, typeArgs: ReadonlyArray<PType>, sourceLocation: SourceLocation): NodeBuilder {
const {
args: [{ avmVersion, name }],
args: [{ avmVersion, name, stateTotals }],
} = parseFunctionArgs({
args,
typeArgs,
Expand All @@ -145,9 +146,26 @@ export class ContractOptionsDecoratorBuilder extends FunctionBuilder {

return new DecoratorDataBuilder(sourceLocation, {
type: 'contract',
avmVersion: avmVersion ? requireAvmVersion(avmVersion) : undefined,
name: name ? requireStringConstant(name).value : undefined,
avmVersion: avmVersion && requireAvmVersion(avmVersion),
name: name && requireStringConstant(name).value,
stateTotals: stateTotals && buildStateTotals(stateTotals),
sourceLocation,
})
}
}

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 undefined
}

return {
globalBytes: tryGetProp('globalBytes'),
globalUints: tryGetProp('globalUints'),
localBytes: tryGetProp('localBytes'),
localUints: tryGetProp('localUints'),
}
}
37 changes: 27 additions & 10 deletions src/awst_build/models/contract-class-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,23 @@ export class ContractClassModel {
this.options = props.options
}

hasExplicitStateTotals() {
return this.options?.stateTotals !== undefined
}

buildContract(compilationSet: CompilationSet): awst.Contract {
let approvalProgram: ContractMethod | null = this.approvalProgram
let clearProgram: ContractMethod | null = this.clearProgram
const methods: ContractMethod[] = [...this.methods, this.ctor]
const methodResolutionOrder: ContractReference[] = []

let firstBaseWithStateTotals: ContractClassModel | undefined = undefined
for (const baseType of this.type.allBases()) {
const cref = ContractReference.fromPType(baseType)
const baseClass = compilationSet.getContractClass(cref)
if (baseClass.hasExplicitStateTotals() && firstBaseWithStateTotals === undefined) {
firstBaseWithStateTotals = baseClass
}
methodResolutionOrder.push(cref)
approvalProgram ??= baseClass.approvalProgram
clearProgram ??= baseClass.clearProgram
Expand Down Expand Up @@ -91,13 +100,21 @@ export class ContractClassModel {
codeInvariant(approvalProgram, 'must have approval')
codeInvariant(clearProgram, 'must have clear')

// TODO: Tally from bases
const stateTotals = new StateTotals({
globalBytes: this.options?.stateTotals?.globalBytes ?? null,
globalUints: this.options?.stateTotals?.globalUints ?? null,
localBytes: this.options?.stateTotals?.localBytes ?? null,
localUints: this.options?.stateTotals?.localUints ?? null,
})
if (!this.hasExplicitStateTotals && firstBaseWithStateTotals) {
logger.warn(
this.options?.sourceLocation ?? this.sourceLocation,
`Contract extends base contract ${firstBaseWithStateTotals.id} with explicit stateTotals, but does not define its own stateTotals. This could result in insufficient reserved state at run time. An empty object may be provided in order to indicate that this contract should revert to the default behaviour`,
)
}

const stateTotals = this.options?.stateTotals
? new StateTotals({
globalBytes: this.options?.stateTotals?.globalBytes ?? null,
globalUints: this.options?.stateTotals?.globalUints ?? null,
localBytes: this.options?.stateTotals?.localBytes ?? null,
localUints: this.options?.stateTotals?.localUints ?? null,
})
: null

// TODO: Tally from bases
const reservedScratchSpace = new Set<bigint>()
Expand All @@ -121,11 +138,11 @@ export class ContractClassModel {
clearProgram,
methodResolutionOrder,
methods,
appState: this.appState, // TODO: Tally from base
stateTotals: stateTotals, // TODO: Tally
appState: this.appState,
stateTotals,
reservedScratchSpace: reservedScratchSpace,
sourceLocation: this.sourceLocation,
avmVersion: this.options?.avmVersion ?? null, // TODO: Allow this to be set with class decorator
avmVersion: this.options?.avmVersion ?? null,
})
}

Expand Down
72 changes: 72 additions & 0 deletions tests/approvals/out/state-totals/BaseWithState.approval.teal
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#pragma version 10

tests/approvals/state-totals.algo.ts::BaseWithState.approvalProgram:
intcblock 0 1
txn ApplicationID
bnz main_after_if_else@2
callsub constructor

main_after_if_else@2:
callsub __puya_arc4_router__
return


// tests/approvals/state-totals.algo.ts::BaseWithState.constructor() -> void:
constructor:
// tests/approvals/state-totals.algo.ts:4
// export class BaseWithState extends Contract {
proto 0 0
// tests/approvals/state-totals.algo.ts:5
// oneGlobal = GlobalState({ initialValue: Uint64(1) })
pushbytes "oneGlobal"
intc_1 // 1
app_global_put
retsub


// tests/approvals/state-totals.algo.ts::BaseWithState.__puya_arc4_router__() -> uint64:
__puya_arc4_router__:
// tests/approvals/state-totals.algo.ts:4
// export class BaseWithState extends Contract {
proto 0 1
txn NumAppArgs
intc_0 // 0
!=
bz __puya_arc4_router___bare_routing@2
b __puya_arc4_router___after_if_else@6

__puya_arc4_router___bare_routing@2:
// tests/approvals/state-totals.algo.ts:4
// export class BaseWithState extends Contract {
txn OnCompletion
intc_0 // 0
swap
match __puya_arc4_router_____algots__.defaultCreate@3
b __puya_arc4_router___switch_case_default@4

__puya_arc4_router_____algots__.defaultCreate@3:
// tests/approvals/state-totals.algo.ts:4
// export class BaseWithState extends Contract {
txn ApplicationID
intc_0 // 0
==
assert // can only call when creating
callsub __algots__.defaultCreate
intc_1 // 1
retsub

__puya_arc4_router___switch_case_default@4:

__puya_arc4_router___after_if_else@6:
// tests/approvals/state-totals.algo.ts:4
// export class BaseWithState extends Contract {
intc_0 // 0
retsub


// tests/approvals/state-totals.algo.ts::BaseWithState.__algots__.defaultCreate() -> void:
__algots__.defaultCreate:
// tests/approvals/state-totals.algo.ts:4
// export class BaseWithState extends Contract {
proto 0 0
retsub
44 changes: 44 additions & 0 deletions tests/approvals/out/state-totals/BaseWithState.arc32.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"hints": {},
"source": {
"approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0cy9hcHByb3ZhbHMvc3RhdGUtdG90YWxzLmFsZ28udHM6OkJhc2VXaXRoU3RhdGUuYXBwcm92YWxQcm9ncmFtOgogICAgaW50Y2Jsb2NrIDAgMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGJueiBtYWluX2FmdGVyX2lmX2Vsc2VAMgogICAgY2FsbHN1YiBjb25zdHJ1Y3RvcgoKbWFpbl9hZnRlcl9pZl9lbHNlQDI6CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyB0ZXN0cy9hcHByb3ZhbHMvc3RhdGUtdG90YWxzLmFsZ28udHM6OkJhc2VXaXRoU3RhdGUuY29uc3RydWN0b3IoKSAtPiB2b2lkOgpjb25zdHJ1Y3RvcjoKICAgIC8vIHRlc3RzL2FwcHJvdmFscy9zdGF0ZS10b3RhbHMuYWxnby50czo0CiAgICAvLyBleHBvcnQgY2xhc3MgQmFzZVdpdGhTdGF0ZSBleHRlbmRzIENvbnRyYWN0IHsKICAgIHByb3RvIDAgMAogICAgLy8gdGVzdHMvYXBwcm92YWxzL3N0YXRlLXRvdGFscy5hbGdvLnRzOjUKICAgIC8vIG9uZUdsb2JhbCA9IEdsb2JhbFN0YXRlKHsgaW5pdGlhbFZhbHVlOiBVaW50NjQoMSkgfSkKICAgIHB1c2hieXRlcyAib25lR2xvYmFsIgogICAgaW50Y18xIC8vIDEKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIKCgovLyB0ZXN0cy9hcHByb3ZhbHMvc3RhdGUtdG90YWxzLmFsZ28udHM6OkJhc2VXaXRoU3RhdGUuX19wdXlhX2FyYzRfcm91dGVyX18oKSAtPiB1aW50NjQ6Cl9fcHV5YV9hcmM0X3JvdXRlcl9fOgogICAgLy8gdGVzdHMvYXBwcm92YWxzL3N0YXRlLXRvdGFscy5hbGdvLnRzOjQKICAgIC8vIGV4cG9ydCBjbGFzcyBCYXNlV2l0aFN0YXRlIGV4dGVuZHMgQ29udHJhY3QgewogICAgcHJvdG8gMCAxCiAgICB0eG4gTnVtQXBwQXJncwogICAgaW50Y18wIC8vIDAKICAgICE9CiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAMgogICAgYiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDYKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0AyOgogICAgLy8gdGVzdHMvYXBwcm92YWxzL3N0YXRlLXRvdGFscy5hbGdvLnRzOjQKICAgIC8vIGV4cG9ydCBjbGFzcyBCYXNlV2l0aFN0YXRlIGV4dGVuZHMgQ29udHJhY3QgewogICAgdHhuIE9uQ29tcGxldGlvbgogICAgaW50Y18wIC8vIDAKICAgIHN3YXAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX19fYWxnb3RzX18uZGVmYXVsdENyZWF0ZUAzCiAgICBiIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3N3aXRjaF9jYXNlX2RlZmF1bHRANAoKX19wdXlhX2FyYzRfcm91dGVyX19fX19hbGdvdHNfXy5kZWZhdWx0Q3JlYXRlQDM6CiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvc3RhdGUtdG90YWxzLmFsZ28udHM6NAogICAgLy8gZXhwb3J0IGNsYXNzIEJhc2VXaXRoU3RhdGUgZXh0ZW5kcyBDb250cmFjdCB7CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgaW50Y18wIC8vIDAKICAgID09CiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIGNyZWF0aW5nCiAgICBjYWxsc3ViIF9fYWxnb3RzX18uZGVmYXVsdENyZWF0ZQogICAgaW50Y18xIC8vIDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fc3dpdGNoX2Nhc2VfZGVmYXVsdEA0OgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUA2OgogICAgLy8gdGVzdHMvYXBwcm92YWxzL3N0YXRlLXRvdGFscy5hbGdvLnRzOjQKICAgIC8vIGV4cG9ydCBjbGFzcyBCYXNlV2l0aFN0YXRlIGV4dGVuZHMgQ29udHJhY3QgewogICAgaW50Y18wIC8vIDAKICAgIHJldHN1YgoKCi8vIHRlc3RzL2FwcHJvdmFscy9zdGF0ZS10b3RhbHMuYWxnby50czo6QmFzZVdpdGhTdGF0ZS5fX2FsZ290c19fLmRlZmF1bHRDcmVhdGUoKSAtPiB2b2lkOgpfX2FsZ290c19fLmRlZmF1bHRDcmVhdGU6CiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvc3RhdGUtdG90YWxzLmFsZ28udHM6NAogICAgLy8gZXhwb3J0IGNsYXNzIEJhc2VXaXRoU3RhdGUgZXh0ZW5kcyBDb250cmFjdCB7CiAgICBwcm90byAwIDAKICAgIHJldHN1Ygo=",
"clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0cy9hcHByb3ZhbHMvc3RhdGUtdG90YWxzLmFsZ28udHM6OkJhc2VXaXRoU3RhdGUuY2xlYXJTdGF0ZVByb2dyYW06CiAgICBwdXNoaW50IDEgLy8gMQogICAgcmV0dXJuCg=="
},
"state": {
"global": {
"num_byte_slices": 0,
"num_uints": 2
},
"local": {
"num_byte_slices": 0,
"num_uints": 0
}
},
"schema": {
"global": {
"declared": {
"oneGlobal": {
"type": "uint64",
"key": "oneGlobal"
},
"twoGlobal": {
"type": "uint64",
"key": "twoGlobal"
}
},
"reserved": {}
},
"local": {
"declared": {},
"reserved": {}
}
},
"contract": {
"name": "BaseWithState",
"methods": [],
"networks": {}
},
"bare_call_config": {
"no_op": "CREATE"
}
}
72 changes: 72 additions & 0 deletions tests/approvals/out/state-totals/BaseWithState.arc56.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"name": "BaseWithState",
"structs": {},
"methods": [],
"arcs": [
22,
28
],
"networks": {},
"state": {
"schema": {
"global": {
"ints": 2,
"bytes": 0
},
"local": {
"ints": 0,
"bytes": 0
}
},
"keys": {
"global": {
"oneGlobal": {
"keyType": "AVMString",
"valueType": "AVMUint64",
"key": "b25lR2xvYmFs"
},
"twoGlobal": {
"keyType": "AVMString",
"valueType": "AVMUint64",
"key": "dHdvR2xvYmFs"
}
},
"local": {},
"box": {}
},
"maps": {
"global": {},
"local": {},
"box": {}
}
},
"bareActions": {
"create": [
"NoOp"
],
"call": []
},
"sourceInfo": {
"approval": {
"sourceInfo": [
{
"pc": [
62
],
"errorMessage": "can only call when creating"
}
],
"pcOffsetMethod": "none"
},
"clear": {
"sourceInfo": [],
"pcOffsetMethod": "none"
}
},
"source": {
"approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0cy9hcHByb3ZhbHMvc3RhdGUtdG90YWxzLmFsZ28udHM6OkJhc2VXaXRoU3RhdGUuYXBwcm92YWxQcm9ncmFtOgogICAgaW50Y2Jsb2NrIDAgMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGJueiBtYWluX2FmdGVyX2lmX2Vsc2VAMgogICAgY2FsbHN1YiBjb25zdHJ1Y3RvcgoKbWFpbl9hZnRlcl9pZl9lbHNlQDI6CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyB0ZXN0cy9hcHByb3ZhbHMvc3RhdGUtdG90YWxzLmFsZ28udHM6OkJhc2VXaXRoU3RhdGUuY29uc3RydWN0b3IoKSAtPiB2b2lkOgpjb25zdHJ1Y3RvcjoKICAgIC8vIHRlc3RzL2FwcHJvdmFscy9zdGF0ZS10b3RhbHMuYWxnby50czo0CiAgICAvLyBleHBvcnQgY2xhc3MgQmFzZVdpdGhTdGF0ZSBleHRlbmRzIENvbnRyYWN0IHsKICAgIHByb3RvIDAgMAogICAgLy8gdGVzdHMvYXBwcm92YWxzL3N0YXRlLXRvdGFscy5hbGdvLnRzOjUKICAgIC8vIG9uZUdsb2JhbCA9IEdsb2JhbFN0YXRlKHsgaW5pdGlhbFZhbHVlOiBVaW50NjQoMSkgfSkKICAgIHB1c2hieXRlcyAib25lR2xvYmFsIgogICAgaW50Y18xIC8vIDEKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIKCgovLyB0ZXN0cy9hcHByb3ZhbHMvc3RhdGUtdG90YWxzLmFsZ28udHM6OkJhc2VXaXRoU3RhdGUuX19wdXlhX2FyYzRfcm91dGVyX18oKSAtPiB1aW50NjQ6Cl9fcHV5YV9hcmM0X3JvdXRlcl9fOgogICAgLy8gdGVzdHMvYXBwcm92YWxzL3N0YXRlLXRvdGFscy5hbGdvLnRzOjQKICAgIC8vIGV4cG9ydCBjbGFzcyBCYXNlV2l0aFN0YXRlIGV4dGVuZHMgQ29udHJhY3QgewogICAgcHJvdG8gMCAxCiAgICB0eG4gTnVtQXBwQXJncwogICAgaW50Y18wIC8vIDAKICAgICE9CiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAMgogICAgYiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDYKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0AyOgogICAgLy8gdGVzdHMvYXBwcm92YWxzL3N0YXRlLXRvdGFscy5hbGdvLnRzOjQKICAgIC8vIGV4cG9ydCBjbGFzcyBCYXNlV2l0aFN0YXRlIGV4dGVuZHMgQ29udHJhY3QgewogICAgdHhuIE9uQ29tcGxldGlvbgogICAgaW50Y18wIC8vIDAKICAgIHN3YXAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX19fYWxnb3RzX18uZGVmYXVsdENyZWF0ZUAzCiAgICBiIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3N3aXRjaF9jYXNlX2RlZmF1bHRANAoKX19wdXlhX2FyYzRfcm91dGVyX19fX19hbGdvdHNfXy5kZWZhdWx0Q3JlYXRlQDM6CiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvc3RhdGUtdG90YWxzLmFsZ28udHM6NAogICAgLy8gZXhwb3J0IGNsYXNzIEJhc2VXaXRoU3RhdGUgZXh0ZW5kcyBDb250cmFjdCB7CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgaW50Y18wIC8vIDAKICAgID09CiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIGNyZWF0aW5nCiAgICBjYWxsc3ViIF9fYWxnb3RzX18uZGVmYXVsdENyZWF0ZQogICAgaW50Y18xIC8vIDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fc3dpdGNoX2Nhc2VfZGVmYXVsdEA0OgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUA2OgogICAgLy8gdGVzdHMvYXBwcm92YWxzL3N0YXRlLXRvdGFscy5hbGdvLnRzOjQKICAgIC8vIGV4cG9ydCBjbGFzcyBCYXNlV2l0aFN0YXRlIGV4dGVuZHMgQ29udHJhY3QgewogICAgaW50Y18wIC8vIDAKICAgIHJldHN1YgoKCi8vIHRlc3RzL2FwcHJvdmFscy9zdGF0ZS10b3RhbHMuYWxnby50czo6QmFzZVdpdGhTdGF0ZS5fX2FsZ290c19fLmRlZmF1bHRDcmVhdGUoKSAtPiB2b2lkOgpfX2FsZ290c19fLmRlZmF1bHRDcmVhdGU6CiAgICAvLyB0ZXN0cy9hcHByb3ZhbHMvc3RhdGUtdG90YWxzLmFsZ28udHM6NAogICAgLy8gZXhwb3J0IGNsYXNzIEJhc2VXaXRoU3RhdGUgZXh0ZW5kcyBDb250cmFjdCB7CiAgICBwcm90byAwIDAKICAgIHJldHN1Ygo=",
"clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0cy9hcHByb3ZhbHMvc3RhdGUtdG90YWxzLmFsZ28udHM6OkJhc2VXaXRoU3RhdGUuY2xlYXJTdGF0ZVByb2dyYW06CiAgICBwdXNoaW50IDEgLy8gMQogICAgcmV0dXJuCg=="
},
"events": [],
"templateVariables": {}
}
5 changes: 5 additions & 0 deletions tests/approvals/out/state-totals/BaseWithState.clear.teal
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma version 10

tests/approvals/state-totals.algo.ts::BaseWithState.clearStateProgram:
pushint 1 // 1
return
49 changes: 49 additions & 0 deletions tests/approvals/out/state-totals/BaseWithState.ssa.ir
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
contract tests/approvals/state-totals.algo.ts::BaseWithState:
program approval:
subroutine @algorandfoundation/algorand-typescript/arc4/index.d.ts::Contract.approvalProgram() -> bool:
block@0: // L1
let reinterpret_bool%0#0: bool = (txn ApplicationID)
goto reinterpret_bool%0#0 ? block@2 : block@1
block@1: // if_body_L1
tests/approvals/state-totals.algo.ts::BaseWithState.constructor()
goto block@2
block@2: // after_if_else_L1
let tmp%0#0: bool = tests/approvals/state-totals.algo.ts::BaseWithState.__puya_arc4_router__()
return tmp%0#0

subroutine tests/approvals/state-totals.algo.ts::BaseWithState.constructor() -> void:
block@0: // L4
(app_global_put "oneGlobal" 1u)
return

subroutine tests/approvals/state-totals.algo.ts::BaseWithState.__puya_arc4_router__() -> bool:
block@0: // L4
let tmp%0#0: uint64 = (txn NumAppArgs)
let tmp%1#0: bool = (!= tmp%0#0 0u)
goto tmp%1#0 ? block@1 : block@2
block@1: // abi_routing_L4
goto block@6
block@2: // bare_routing_L4
let tmp%2#0: uint64 = (txn OnCompletion)
switch tmp%2#0 {0u => block@3, * => block@4}
block@3: // __algots__.defaultCreate_L4
let tmp%3#0: uint64 = (txn ApplicationID)
let tmp%4#0: bool = (== tmp%3#0 0u)
(assert tmp%4#0) // can only call when creating
tests/approvals/state-totals.algo.ts::BaseWithState.__algots__.defaultCreate()
return 1u
block@4: // switch_case_default_L4
goto block@5
block@5: // switch_case_next_L4
goto block@6
block@6: // after_if_else_L4
return 0u

subroutine tests/approvals/state-totals.algo.ts::BaseWithState.__algots__.defaultCreate() -> void:
block@0: // L4
return

program clear-state:
subroutine @algorandfoundation/algorand-typescript/base-contract.d.ts::BaseContract.clearStateProgram() -> bool:
block@0: // L1
return 1u
Loading

0 comments on commit 52ebc65

Please sign in to comment.