Skip to content

Commit f17f73e

Browse files
authored
Start work on Teal 6 (AVM 1.1) (#2974)
Start work on Teal 6 (AVM 1.1) vFuture, LogicVersion changed to 6 Support RekeyTo field, and Keyreg transactions
1 parent fbd75f7 commit f17f73e

16 files changed

+590
-97
lines changed

config/consensus.go

+3
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,9 @@ func initConsensusProtocols() {
10421042
vFuture.CompactCertWeightThreshold = (1 << 32) * 30 / 100
10431043
vFuture.CompactCertSecKQ = 128
10441044

1045+
// Enable TEAL 6 / AVM 1.1
1046+
vFuture.LogicSigVersion = 6
1047+
10451048
Consensus[protocol.ConsensusFuture] = vFuture
10461049
}
10471050

data/transactions/logic/assembler_test.go

+16-15
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ intc 1
134134
mulw
135135
`
136136

137-
const v2Nonsense = `
137+
const v2Nonsense = v1Nonsense + `
138138
dup2
139139
pop
140140
pop
@@ -219,7 +219,7 @@ txn FreezeAssetAccount
219219
txn FreezeAssetFrozen
220220
`
221221

222-
const v3Nonsense = `
222+
const v3Nonsense = v2Nonsense + `
223223
assert
224224
min_balance
225225
int 0x031337 // get bit 1, negate it, put it back
@@ -248,7 +248,7 @@ pushbytes "john"
248248

249249
// Keep in mind, only use existing int and byte constants, or else use
250250
// push* instead. The idea is to not cause the *cblocks to change.
251-
const v4Nonsense = `
251+
const v4Nonsense = v3Nonsense + `
252252
int 1
253253
pushint 2000
254254
int 0
@@ -294,7 +294,7 @@ gaids
294294
int 100
295295
`
296296

297-
const v5Nonsense = `
297+
const v5Nonsense = v4Nonsense + `
298298
app_params_get AppExtraProgramPages
299299
cover 1
300300
uncover 1
@@ -342,12 +342,16 @@ ecdsa_pk_recover Secp256k1
342342
itxna Logs 3
343343
`
344344

345+
const v6Nonsense = v5Nonsense + `
346+
`
347+
345348
var nonsense = map[uint64]string{
346349
1: v1Nonsense,
347-
2: v1Nonsense + v2Nonsense,
348-
3: v1Nonsense + v2Nonsense + v3Nonsense,
349-
4: v1Nonsense + v2Nonsense + v3Nonsense + v4Nonsense,
350-
5: v1Nonsense + v2Nonsense + v3Nonsense + v4Nonsense + v5Nonsense,
350+
2: v2Nonsense,
351+
3: v3Nonsense,
352+
4: v4Nonsense,
353+
5: v5Nonsense,
354+
6: v6Nonsense,
351355
}
352356

353357
var compiled = map[uint64]string{
@@ -356,6 +360,7 @@ var compiled = map[uint64]string{
356360
3: "032008b7a60cf8acd19181cf959a12f8acd19181cf951af8acd19181cf15f8acd191810f01020026050212340c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d024242047465737400320032013202320328292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e0102222324252104082209240a220b230c240d250e230f23102311231223132314181b1c2b171615400003290349483403350222231d4a484848482a50512a63222352410003420000432105602105612105270463484821052b62482b642b65484821052b2106662b21056721072b682b692107210570004848210771004848361c0037001a0031183119311b311d311e311f3120210721051e312131223123312431253126312731283129312a312b312c312d312e312f4478222105531421055427042106552105082106564c4d4b02210538212106391c0081e80780046a6f686e",
357361
4: "042004010200b7a60c26040242420c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f23102311231223132314181b1c28171615400003290349483403350222231d4a484848482a50512a632223524100034200004322602261222b634848222862482864286548482228236628226724286828692422700048482471004848361c0037001a0031183119311b311d311e311f312024221e312131223123312431253126312731283129312a312b312c312d312e312f44782522531422542b2355220823564c4d4b0222382123391c0081e80780046a6f686e2281d00f24231f880003420001892223902291922394239593a0a1a2a3a4a5a6a7a8a9aaabacadae23af3a00003b003c003d8164",
358362
5: "052004010002b7a60c26050242420c68656c6c6f20776f726c6421070123456789abcd208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292b0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f23102311231223132314181b1c28171615400003290349483403350222231d4a484848482b50512a632223524100034200004322602261222704634848222862482864286548482228246628226723286828692322700048482371004848361c0037001a0031183119311b311d311e311f312023221e312131223123312431253126312731283129312a312b312c312d312e312f447825225314225427042455220824564c4d4b0222382124391c0081e80780046a6f686e2281d00f23241f880003420001892224902291922494249593a0a1a2a3a4a5a6a7a8a9aaabacadae24af3a00003b003c003d816472064e014f012a57000823810858235b235a2359b03139330039b1b200b322c01a23c1001a2323c21a23c3233e233f8120af06002a494905002a49490700b53a03",
363+
6: "062004010002b7a60c26050242420c68656c6c6f20776f726c6421070123456789abcd208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292b0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f23102311231223132314181b1c28171615400003290349483403350222231d4a484848482b50512a632223524100034200004322602261222704634848222862482864286548482228246628226723286828692322700048482371004848361c0037001a0031183119311b311d311e311f312023221e312131223123312431253126312731283129312a312b312c312d312e312f447825225314225427042455220824564c4d4b0222382124391c0081e80780046a6f686e2281d00f23241f880003420001892224902291922494249593a0a1a2a3a4a5a6a7a8a9aaabacadae24af3a00003b003c003d816472064e014f012a57000823810858235b235a2359b03139330039b1b200b322c01a23c1001a2323c21a23c3233e233f8120af06002a494905002a49490700b53a03",
359364
}
360365

361366
func pseudoOp(opcode string) bool {
@@ -381,6 +386,7 @@ func TestAssemble(t *testing.T) {
381386
// This doesn't have to be a sensible program to run, it just has to compile.
382387

383388
t.Parallel()
389+
require.Equal(t, LogicVersion, len(nonsense))
384390
for v := uint64(2); v <= AssemblerMaxVersion; v++ {
385391
t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) {
386392
for _, spec := range OpSpecs {
@@ -1374,12 +1380,6 @@ func TestAssembleDisassembleCycle(t *testing.T) {
13741380
// Disassembly won't necessarily perfectly recreate the source text, but assembling the result of Disassemble() should be the same program bytes.
13751381
t.Parallel()
13761382

1377-
tests := map[uint64]string{
1378-
1: v1Nonsense,
1379-
2: v1Nonsense + v2Nonsense,
1380-
3: v1Nonsense + v2Nonsense + v3Nonsense,
1381-
}
1382-
13831383
// This confirms that each program compiles to the same bytes
13841384
// (except the leading version indicator), when compiled under
13851385
// original version, unspecified version (so it should pick up
@@ -1388,7 +1388,8 @@ func TestAssembleDisassembleCycle(t *testing.T) {
13881388
// optimizations in later versions that change the bytecode
13891389
// emitted. But currently it is, so we test it for now to
13901390
// catch any suprises.
1391-
for v, source := range tests {
1391+
require.Equal(t, LogicVersion, len(nonsense))
1392+
for v, source := range nonsense {
13921393
t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) {
13931394
ops := testProg(t, source, v)
13941395
t2, err := Disassemble(ops.Program)

data/transactions/logic/eval.go

+49-22
Original file line numberDiff line numberDiff line change
@@ -3741,11 +3741,12 @@ func (cx *EvalContext) stackIntoTxnField(sv stackValue, fs txnFieldSpec, txn *tr
37413741
err = fmt.Errorf("Type arg not a byte array")
37423742
return
37433743
}
3744-
txType, ok := innerTxnTypes[string(sv.Bytes)]
3745-
if ok {
3746-
txn.Type = txType
3744+
txType := string(sv.Bytes)
3745+
ver, ok := innerTxnTypes[txType]
3746+
if ok && ver <= cx.version {
3747+
txn.Type = protocol.TxType(txType)
37473748
} else {
3748-
err = fmt.Errorf("%s is not a valid Type for itxn_field", sv.Bytes)
3749+
err = fmt.Errorf("%s is not a valid Type for itxn_field", txType)
37493750
}
37503751
case TypeEnum:
37513752
var i uint64
@@ -3755,9 +3756,9 @@ func (cx *EvalContext) stackIntoTxnField(sv stackValue, fs txnFieldSpec, txn *tr
37553756
}
37563757
// i != 0 is so that the error reports 0 instead of Unknown
37573758
if i != 0 && i < uint64(len(TxnTypeNames)) {
3758-
txType, ok := innerTxnTypes[TxnTypeNames[i]]
3759-
if ok {
3760-
txn.Type = txType
3759+
ver, ok := innerTxnTypes[TxnTypeNames[i]]
3760+
if ok && ver <= cx.version {
3761+
txn.Type = protocol.TxType(TxnTypeNames[i])
37613762
} else {
37623763
err = fmt.Errorf("%s is not a valid Type for itxn_field", TxnTypeNames[i])
37633764
}
@@ -3768,14 +3769,48 @@ func (cx *EvalContext) stackIntoTxnField(sv stackValue, fs txnFieldSpec, txn *tr
37683769
txn.Sender, err = cx.availableAccount(sv)
37693770
case Fee:
37703771
txn.Fee.Raw, err = sv.uint()
3771-
// FirstValid, LastValid unsettable: no motivation
3772-
// Note unsettable: would be strange, as this "Note" would not end up "chain-visible"
3772+
// FirstValid, LastValid unsettable: little motivation (maybe a app call
3773+
// wants to inspect?) If we set, make sure they are legal, both for current
3774+
// round, and separation by MaxLifetime (check lifetime in submit, not here)
3775+
case Note:
3776+
if len(sv.Bytes) > cx.Proto.MaxTxnNoteBytes {
3777+
err = fmt.Errorf("%s may not exceed %d bytes", fs.field, cx.Proto.MaxTxnNoteBytes)
3778+
} else {
3779+
txn.Note = make([]byte, len(sv.Bytes))
3780+
copy(txn.Note[:], sv.Bytes)
3781+
}
37733782
// GenesisID, GenesisHash unsettable: surely makes no sense
37743783
// Group unsettable: Can't make groups from AVM (yet?)
37753784
// Lease unsettable: This seems potentially useful.
3776-
// RekeyTo unsettable: Feels dangerous for first release.
37773785

3778-
// KeyReg not allowed yet, so no fields settable
3786+
case RekeyTo:
3787+
txn.RekeyTo, err = sv.address()
3788+
3789+
// KeyReg
3790+
case VotePK:
3791+
if len(sv.Bytes) != 32 {
3792+
err = fmt.Errorf("%s must be 32 bytes", fs.field)
3793+
} else {
3794+
copy(txn.VotePK[:], sv.Bytes)
3795+
}
3796+
case SelectionPK:
3797+
if len(sv.Bytes) != 32 {
3798+
err = fmt.Errorf("%s must be 32 bytes", fs.field)
3799+
} else {
3800+
copy(txn.SelectionPK[:], sv.Bytes)
3801+
}
3802+
case VoteFirst:
3803+
var round uint64
3804+
round, err = sv.uint()
3805+
txn.VoteFirst = basics.Round(round)
3806+
case VoteLast:
3807+
var round uint64
3808+
round, err = sv.uint()
3809+
txn.VoteLast = basics.Round(round)
3810+
case VoteKeyDilution:
3811+
txn.VoteKeyDilution, err = sv.uint()
3812+
case Nonparticipation:
3813+
txn.Nonparticipation, err = sv.bool()
37793814

37803815
// Payment
37813816
case Receiver:
@@ -3820,7 +3855,7 @@ func (cx *EvalContext) stackIntoTxnField(sv stackValue, fs txnFieldSpec, txn *tr
38203855
txn.AssetParams.URL, err = sv.string(cx.Proto.MaxAssetURLBytes)
38213856
case ConfigAssetMetadataHash:
38223857
if len(sv.Bytes) != 32 {
3823-
err = fmt.Errorf("ConfigAssetMetadataHash must be 32 bytes")
3858+
err = fmt.Errorf("%s must be 32 bytes", fs.field)
38243859
} else {
38253860
copy(txn.AssetParams.MetadataHash[:], sv.Bytes)
38263861
}
@@ -3857,7 +3892,8 @@ func opTxField(cx *EvalContext) {
38573892
field := TxnField(cx.program[cx.pc+1])
38583893
fs, ok := txnFieldSpecByField[field]
38593894
if !ok || fs.itxVersion == 0 || fs.itxVersion > cx.version {
3860-
cx.err = fmt.Errorf("invalid itxn_field field %d", field)
3895+
cx.err = fmt.Errorf("invalid itxn_field %s", field)
3896+
return
38613897
}
38623898
sv := cx.stack[last]
38633899
cx.err = cx.stackIntoTxnField(sv, fs, &cx.subtxn.Txn)
@@ -3880,15 +3916,6 @@ func opTxSubmit(cx *EvalContext) {
38803916
return
38813917
}
38823918

3883-
// Error out on anything unusual. Allow pay, axfer.
3884-
switch cx.subtxn.Txn.Type {
3885-
case protocol.PaymentTx, protocol.AssetTransferTx, protocol.AssetConfigTx, protocol.AssetFreezeTx:
3886-
// only pay, axfer, acfg, afrz for now
3887-
default:
3888-
cx.err = fmt.Errorf("Invalid inner transaction type %#v", cx.subtxn.Txn.Type)
3889-
return
3890-
}
3891-
38923919
// The goal is to follow the same invariants used by the
38933920
// transaction pool. Namely that any transaction that makes it
38943921
// to Perform (which is equivalent to eval.applyTransaction)

data/transactions/logic/evalAppTxn_test.go

+91-7
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,28 @@ import (
2525
"github.com/stretchr/testify/require"
2626
)
2727

28-
func TestActionTypes(t *testing.T) {
28+
func TestInnerTypesV5(t *testing.T) {
29+
v5, _ := makeSampleEnvWithVersion(5)
30+
// not alllowed in v5
31+
testApp(t, "itxn_begin; byte \"keyreg\"; itxn_field Type; itxn_submit; int 1;", v5, "keyreg is not a valid Type for itxn_field")
32+
testApp(t, "itxn_begin; int keyreg; itxn_field TypeEnum; itxn_submit; int 1;", v5, "keyreg is not a valid Type for itxn_field")
33+
}
34+
35+
func TestCurrentInnerTypes(t *testing.T) {
2936
ep, ledger := makeSampleEnv()
3037
testApp(t, "itxn_submit; int 1;", ep, "itxn_submit without itxn_begin")
3138
testApp(t, "int pay; itxn_field TypeEnum; itxn_submit; int 1;", ep, "itxn_field without itxn_begin")
32-
testApp(t, "itxn_begin; itxn_submit; int 1;", ep, "Invalid inner transaction type")
39+
testApp(t, "itxn_begin; itxn_submit; int 1;", ep, "unknown tx type")
3340
// bad type
3441
testApp(t, "itxn_begin; byte \"pya\"; itxn_field Type; itxn_submit; int 1;", ep, "pya is not a valid Type")
3542
// mixed up the int form for the byte form
3643
testApp(t, obfuscate("itxn_begin; int pay; itxn_field Type; itxn_submit; int 1;"), ep, "Type arg not a byte array")
3744
// or vice versa
3845
testApp(t, obfuscate("itxn_begin; byte \"pay\"; itxn_field TypeEnum; itxn_submit; int 1;"), ep, "not a uint64")
3946

40-
// good types, not alllowed yet
41-
testApp(t, "itxn_begin; byte \"keyreg\"; itxn_field Type; itxn_submit; int 1;", ep, "keyreg is not a valid Type for itxn_field")
47+
// good types, not allowed yet
4248
testApp(t, "itxn_begin; byte \"appl\"; itxn_field Type; itxn_submit; int 1;", ep, "appl is not a valid Type for itxn_field")
4349
// same, as enums
44-
testApp(t, "itxn_begin; int keyreg; itxn_field TypeEnum; itxn_submit; int 1;", ep, "keyreg is not a valid Type for itxn_field")
4550
testApp(t, "itxn_begin; int appl; itxn_field TypeEnum; itxn_submit; int 1;", ep, "appl is not a valid Type for itxn_field")
4651
testApp(t, "itxn_begin; int 42; itxn_field TypeEnum; itxn_submit; int 1;", ep, "42 is not a valid TypeEnum")
4752
testApp(t, "itxn_begin; int 0; itxn_field TypeEnum; itxn_submit; int 1;", ep, "0 is not a valid TypeEnum")
@@ -58,6 +63,10 @@ func TestActionTypes(t *testing.T) {
5863
testApp(t, "itxn_begin; int acfg; itxn_field TypeEnum; itxn_submit; int 1;", ep, "insufficient balance")
5964
testApp(t, "itxn_begin; int afrz; itxn_field TypeEnum; itxn_submit; int 1;", ep, "insufficient balance")
6065

66+
// alllowed since v6
67+
testApp(t, "itxn_begin; byte \"keyreg\"; itxn_field Type; itxn_submit; int 1;", ep, "insufficient balance")
68+
testApp(t, "itxn_begin; int keyreg; itxn_field TypeEnum; itxn_submit; int 1;", ep, "insufficient balance")
69+
6170
// Establish 888 as the app id, and fund it.
6271
ledger.NewApp(ep.Txn.Txn.Receiver, 888, basics.AppParams{})
6372
ledger.NewAccount(basics.AppIndex(888).Address(), 200000)
@@ -220,6 +229,30 @@ func TestRekeyPay(t *testing.T) {
220229
// See explanation in logicLedger's Perform()
221230
}
222231

232+
func TestRekeyBack(t *testing.T) {
233+
payAndUnkey := `
234+
itxn_begin
235+
itxn_field Amount
236+
itxn_field Receiver
237+
itxn_field Sender
238+
int pay
239+
itxn_field TypeEnum
240+
txn Sender
241+
itxn_field RekeyTo
242+
itxn_submit
243+
`
244+
245+
ep, ledger := makeSampleEnv()
246+
ledger.NewApp(ep.Txn.Txn.Receiver, 888, basics.AppParams{})
247+
testApp(t, "txn Sender; balance; int 0; ==;", ep)
248+
testApp(t, "txn Sender; txn Accounts 1; int 100"+payAndUnkey, ep, "unauthorized")
249+
ledger.NewAccount(ep.Txn.Txn.Sender, 120+3*ep.Proto.MinTxnFee)
250+
ledger.Rekey(ep.Txn.Txn.Sender, basics.AppIndex(888).Address())
251+
testApp(t, "txn Sender; txn Accounts 1; int 100"+payAndUnkey+"; int 1", ep)
252+
// now rekeyed back to original
253+
testApp(t, "txn Sender; txn Accounts 1; int 100"+payAndUnkey, ep, "unauthorized")
254+
}
255+
223256
func TestDefaultSender(t *testing.T) {
224257
pay := `
225258
itxn_begin
@@ -320,7 +353,7 @@ func TestExtraFields(t *testing.T) {
320353
"non-zero fields for type axfer")
321354
}
322355

323-
func TestBadField(t *testing.T) {
356+
func TestBadFieldV5(t *testing.T) {
324357
pay := `
325358
itxn_begin
326359
int 7; itxn_field AssetAmount;
@@ -334,12 +367,34 @@ func TestBadField(t *testing.T) {
334367
itxn_submit
335368
`
336369

337-
ep, ledger := makeSampleEnv()
370+
ep, ledger := makeSampleEnvWithVersion(5)
338371
ledger.NewApp(ep.Txn.Txn.Receiver, 888, basics.AppParams{})
339372
testApp(t, "global CurrentApplicationAddress; txn Accounts 1; int 100"+pay, ep,
340373
"invalid itxn_field RekeyTo")
341374
}
342375

376+
func TestBadField(t *testing.T) {
377+
pay := `
378+
itxn_begin
379+
int 7; itxn_field AssetAmount;
380+
itxn_field Amount
381+
itxn_field Receiver
382+
itxn_field Sender
383+
int pay
384+
itxn_field TypeEnum
385+
txn Receiver
386+
itxn_field RekeyTo // ALLOWED, since v6
387+
int 10
388+
itxn_field FirstValid // NOT ALLOWED
389+
itxn_submit
390+
`
391+
392+
ep, ledger := makeSampleEnv()
393+
ledger.NewApp(ep.Txn.Txn.Receiver, 888, basics.AppParams{})
394+
testApp(t, "global CurrentApplicationAddress; txn Accounts 1; int 100"+pay, ep,
395+
"invalid itxn_field FirstValid")
396+
}
397+
343398
func TestNumInner(t *testing.T) {
344399
pay := `
345400
itxn_begin
@@ -434,3 +489,32 @@ func TestAssetFreeze(t *testing.T) {
434489
require.NoError(t, err)
435490
require.Equal(t, false, holding.Frozen)
436491
}
492+
493+
func TestFieldSetting(t *testing.T) {
494+
ep, ledger := makeSampleEnv()
495+
ledger.NewApp(ep.Txn.Txn.Receiver, 888, basics.AppParams{})
496+
ledger.NewAccount(ledger.ApplicationID().Address(), 10*defaultEvalProto().MinTxnFee)
497+
testApp(t, "itxn_begin; int 500; bzero; itxn_field Note; int 1", ep)
498+
testApp(t, "itxn_begin; int 501; bzero; itxn_field Note; int 1", ep,
499+
"Note may not exceed")
500+
501+
testApp(t, "itxn_begin; int 32; bzero; itxn_field VotePK; int 1", ep)
502+
testApp(t, "itxn_begin; int 31; bzero; itxn_field VotePK; int 1", ep,
503+
"VotePK must be 32")
504+
505+
testApp(t, "itxn_begin; int 32; bzero; itxn_field SelectionPK; int 1", ep)
506+
testApp(t, "itxn_begin; int 33; bzero; itxn_field SelectionPK; int 1", ep,
507+
"SelectionPK must be 32")
508+
509+
testApp(t, "itxn_begin; int 32; bzero; itxn_field RekeyTo; int 1", ep)
510+
testApp(t, "itxn_begin; int 31; bzero; itxn_field RekeyTo; int 1", ep,
511+
"not an address")
512+
513+
testApp(t, "itxn_begin; int 6; bzero; itxn_field ConfigAssetUnitName; int 1", ep)
514+
testApp(t, "itxn_begin; int 7; bzero; itxn_field ConfigAssetUnitName; int 1", ep,
515+
"value is too long")
516+
517+
testApp(t, "itxn_begin; int 12; bzero; itxn_field ConfigAssetName; int 1", ep)
518+
testApp(t, "itxn_begin; int 13; bzero; itxn_field ConfigAssetName; int 1", ep,
519+
"value is too long")
520+
}

data/transactions/logic/evalStateful_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2493,7 +2493,7 @@ func TestPooledAppCallsVerifyOp(t *testing.T) {
24932493
partitiontest.PartitionTest(t)
24942494
t.Parallel()
24952495

2496-
source := `#pragma version 5
2496+
source := `
24972497
global CurrentApplicationID
24982498
pop
24992499
byte 0x01

0 commit comments

Comments
 (0)