-
Notifications
You must be signed in to change notification settings - Fork 524
Description
@dragmz identified an unusual issue where some existing smart contracts were unable to be assmbled after being disassembled.
The two application IDs originally identified as having this problem were: 2747284875 and 2309798439.
After a little investigating I discovered that during disassembly, any unused subroutines/labels doesn't get given a label. Which should be fine since labels are there for us humans, and any branch/call opcode is actually using a signed int16 offset.
The problem however, is when an unused subroutine uses the proto opcode. This results in any use of frame_dig or frame_bury now being globally scoped and these errors being produced.
Example:
Using one of the existing programs.
% curl -s https://mainnet-api.algonode.cloud/v2/applications/2747284875 \
| jq -r '.params."approval-program"' \
| base64 -d \
| goal clerk compile -D - \
| goal clerk compile -
-: 829: itxn_field AssetReceiver arg 0 wanted type address got uint64
-: 834: itxn_field AssetAmount arg 0 wanted type uint64 got []byte
-: 839: itxn_field XferAsset arg 0 wanted type uint64 got []byte
-: 859: itxn_field AssetReceiver arg 0 wanted type address got uint64
-: 864: itxn_field AssetAmount arg 0 wanted type uint64 got []byte
-: 869: itxn_field XferAsset arg 0 wanted type uint64 got []byte
-: 6 errors
MRE
This program will happily compile and deploy. But disassembling it results in the "unusedSubroutine" label being omitted.
#pragma version 12
callsub usedSubroutine
pushint 1
return
usedSubroutine:
retsub
unusedSubroutine:
proto 0 0
pushint 0
pushint 1
frame_bury 0
pop
retsub
Assemble + Disassemble: Label not given to unusedSubroutine
% goal clerk compile test.teal -o - \
| goal clerk compile -D -
#pragma version 12
callsub label1
pushint 1
return
label1:
retsub
proto 0 0 // <--- no label
pushint 0
pushint 1
frame_bury 0
pop
retsub
Assemble + Dissasmble + Assemble: Errors
% goal clerk compile test.teal -o - \
| goal clerk compile -D - \
| goal clerk compile -
-: 1 error: 10: frame_bury above stack
-: 1 error: 10: frame_bury above stack
If you comment out the usedSubroutine all together, you'll get a different error: proto must be unreachable from previous PC.
% goal clerk compile test.teal -o - \
| goal clerk compile -D - \
| goal clerk compile -
-: 1 error: 4: proto must be unreachable from previous PC
-: 1 error: 4: proto must be unreachable from previous PC