How to understand this "decompiled" program?

  • #1

fluidistic

Gold Member
3,917
243
I am sinking deeply into the cryptocurrencies world. There is a website that shows a "smart contract", a piece of code that is supposed to provide rewards for "staking" a particular token, where the rewards is two different tokens (I am not even sure in which proportion). Usually people who wants to join the "staking pool" have to agree/sign the contract, and they are free to look up at the code.

Code:
#pragma version 3
    int 0
    txn ApplicationID
    ==
    bz label1
    byte base64 Qw==
    txn Sender
    app_global_put
    byte base64 R1Q=
    global LatestTimestamp
    app_global_put
    byte base64 R0E=
    int 0
    app_global_put
    byte base64 R1NT
    int 0
    app_global_put
    bytec 4 
    int 0
    app_global_put
    bytec 5 
    int 0
    app_global_put
    int 1
    return
label1:
    int 5
    txn OnCompletion
    ==
    bz label2
    int 0
    return
label2:
    int 4
    txn OnCompletion
    ==
    bz label3
    byte base64 Qw==
    app_global_get
    txn Sender
    ==
    txn NumAppArgs
    int 4
    ==
    &&
    assert
    bytec 6 
    txna ApplicationArgs 0
    app_global_put
    bytec 7 
    txna ApplicationArgs 1
    btoi
    app_global_put
    bytec 8 
    txna ApplicationArgs 2
    btoi
    app_global_put
    bytec 9 
    txna ApplicationArgs 3
    btoi
    app_global_put
    int 1
    return
label3:
    intc 4 
    txn OnCompletion
    ==
    bnz label4
    int 0
    txn NumAppArgs
    ==
    bz label5
    int 1
    txn OnCompletion
    ==
    assert
    int 1
    return
label5:
    txna ApplicationArgs 0
    bytec 10 
    ==
    bnz label6
    txna ApplicationArgs 0
    bytec 11 
    ==
    bnz label7
    txna ApplicationArgs 0
    bytec 12 
    ==
    bnz label8
    txna ApplicationArgs 0
    bytec 13 
    ==
    bnz label9
    txna ApplicationArgs 0
    bytec 14 
    ==
    bnz label10
    txna ApplicationArgs 0
    bytec 15 
    ==
    bnz label11
    txna ApplicationArgs 0
    bytec 16 
    ==
    bnz label12
    int 0
    return
label10:
    byte base64 Qw==
    app_global_get
    txn Sender
    ==
    assert
    int 1
    bytec 17 
    app_global_get_ex
    assert
    intc 4 
    bytec 18 
    app_global_get_ex
    assert
    *
    intc 5 
    /
    store 1
    bytec 4 
    bytec 4 
    app_global_get
    load 1
    intc 6 
    intc 4 
    bytec 19 
    app_global_get_ex
    assert
    -
    *
    intc 6 
    /
    +
    app_global_put
    int 1
    return
label11:
    gtxn 0 ApplicationID
    bytec 9 
    app_global_get
    ==
    assert
    byte base64 R0E=
    app_global_get
    store 1
    global LatestTimestamp
    byte base64 R1Q=
    app_global_get
    -
    intc 7 
    /
    store 8
    load 8
    load 1
    *
    byte base64 R1NT
    app_global_get
    +
    store 2
    int 0
    bytec 20 
    app_local_get
    store 1
    global LatestTimestamp
    int 0
    bytec 21 
    app_local_get
    -
    intc 7 
    /
    store 8
    load 8
    load 1
    *
    int 0
    bytec 22 
    app_local_get
    +
    store 3
    bytec 4 
    app_global_get
    load 2
    load 3
    /
    /
    store 6
    load 6
    gtxn 3 AssetAmount
    >=
    assert
    bytec 4 
    bytec 4 
    app_global_get
    gtxn 3 AssetAmount
    -
    app_global_put
    int 1
    return
label6:
    gtxn 0 ApplicationID
    bytec 9 
    app_global_get
    ==
    assert
    byte base64 R0E=
    app_global_get
    store 1
    global LatestTimestamp
    byte base64 R1Q=
    app_global_get
    -
    intc 7 
    /
    store 8
    load 8
    load 1
    *
    byte base64 R1NT
    app_global_get
    +
    store 2
    byte base64 R1NT
    load 2
    app_global_put
    byte base64 R0E=
    app_global_get
    gtxn 2 AssetAmount
    +
    store 3
    byte base64 R0E=
    load 3
    app_global_put
    load 8
    int 1
    >=
    bz label13
    byte base64 R1Q=
    byte base64 R1Q=
    app_global_get
    load 8
    intc 7 
    *
    +
    app_global_put
label13:
    int 0
    txn ApplicationID
    bytec 20 
    app_local_get_ex
    bz label14
    int 0
    bytec 20 
    app_local_get
    store 1
    global LatestTimestamp
    int 0
    bytec 21 
    app_local_get
    -
    intc 7 
    /
    store 8
    load 8
    load 1
    *
    int 0
    bytec 22 
    app_local_get
    +
    store 2
    int 0
    bytec 22 
    load 2
    app_local_put
    int 0
    bytec 20 
    app_local_get
    gtxn 2 AssetAmount
    +
    store 3
    int 0
    bytec 20 
    load 3
    app_local_put
    load 8
    int 1
    >=
    bz label15
    int 0
    bytec 21 
    int 0
    bytec 21 
    app_local_get
    load 8
    intc 7 
    *
    +
    app_local_put
label15:
    int 1
    return
label7:
    gtxn 0 ApplicationID
    bytec 9 
    app_global_get
    ==
    assert
    byte base64 R0E=
    app_global_get
    store 1
    global LatestTimestamp
    byte base64 R1Q=
    app_global_get
    -
    intc 7 
    /
    store 8
    load 8
    load 1
    *
    byte base64 R1NT
    app_global_get
    +
    store 2
    byte base64 R1NT
    load 2
    app_global_put
    byte base64 R0E=
    app_global_get
    gtxn 2 AssetAmount
    -
    store 3
    byte base64 R0E=
    load 3
    app_global_put
    load 8
    int 1
    >=
    bz label16
    byte base64 R1Q=
    byte base64 R1Q=
    app_global_get
    load 8
    intc 7 
    *
    +
    app_global_put
label16:
    int 0
    bytec 20 
    app_local_get
    store 1
    global LatestTimestamp
    int 0
    bytec 21 
    app_local_get
    -
    intc 7 
    /
    store 8
    load 8
    load 1
    *
    int 0
    bytec 22 
    app_local_get
    +
    store 2
    int 0
    bytec 22 
    load 2
    app_local_put
    int 0
    bytec 20 
    app_local_get
    gtxn 2 AssetAmount
    -
    store 3
    int 0
    bytec 20 
    load 3
    app_local_put
    load 8
    int 1
    >=
    bz label17
    int 0
    bytec 21 
    int 0
    bytec 21 
    app_local_get
    load 8
    intc 7 
    *
    +
    app_local_put
label17:
    int 1
    return
label9:
    global GroupSize
    int 5
    ==
    bytec 23 
    bytec 5 
    app_global_get
    app_global_put
    byte base64 Qw==
    app_global_get
    txn Sender
    ==
    &&
    assert
    int 1
    balance
    int 1
    min_balance
    -
    int 1
    byte base64 R0E=
    app_global_get_ex
    assert
    bytec 5 
    app_global_get
    +
    -
    intc 8 
    *
    intc 6 
    /
    store 1
    bytec 5 
    bytec 5 
    app_global_get
    load 1
    +
    app_global_put
    int 1
    return
label8:
    gtxn 0 ApplicationID
    bytec 9 
    app_global_get
    ==
    assert
    byte base64 R0E=
    app_global_get
    store 1
    global LatestTimestamp
    byte base64 R1Q=
    app_global_get
    -
    intc 7 
    /
    store 8
    load 8
    load 1
    *
    byte base64 R1NT
    app_global_get
    +
    store 2
    byte base64 R1NT
    load 2
    app_global_put
    load 8
    int 1
    >=
    bz label18
    byte base64 R1Q=
    byte base64 R1Q=
    app_global_get
    load 8
    intc 7 
    *
    +
    app_global_put
label18:
    int 0
    bytec 20 
    app_local_get
    store 1
    global LatestTimestamp
    int 0
    bytec 21 
    app_local_get
    -
    intc 7 
    /
    store 8
    load 8
    load 1
    *
    int 0
    bytec 22 
    app_local_get
    +
    store 2
    int 0
    bytec 22 
    load 2
    app_local_put
    bytec 5 
    app_global_get
    byte base64 R1NT
    app_global_get
    int 0
    bytec 22 
    app_local_get
    /
    /
    store 4
    load 4
    gtxn 4 Amount
    >=
    assert
    bytec 5 
    bytec 5 
    app_global_get
    gtxn 4 Amount
    -
    app_global_put
    byte base64 R1NT
    byte base64 R1NT
    app_global_get
    int 0
    bytec 22 
    app_local_get
    -
    app_global_put
    int 0
    bytec 22 
    int 0
    app_local_put
    load 8
    int 1
    >=
    bz label19
    int 0
    bytec 21 
    int 0
    bytec 21 
    app_local_get
    load 8
    intc 7 
    *
    +
    app_local_put
label19:
    int 1
    return
label14:
    int 0
    bytec 20 
    gtxn 2 AssetAmount
    app_local_put
    int 0
    bytec 21 
    byte base64 R1Q=
    app_global_get
    app_local_put
    int 0
    bytec 22 
    int 0
    app_local_put
    int 1
    return
label12:
    byte base64 Qw==
    app_global_get
    txn Sender
    ==
    assert
    byte base64 Qw==
    txna ApplicationArgs 1
    app_global_put
    int 1
    return
label4:
    int 1
    return

If there is some problem with the display, the original code can be found there: https://algoexplorer.io/application/233725850.
I have a very hard time to understand even the slightest thing out of this code (I know some Python, a little bit of Fortran), I am not even sure whether this corresponds to a programming language (doesn't look like entirely as assembly, isn't it?). Any pointer on how to understand the code is welcome.
 

Answers and Replies

  • #2
My guess is that it is compiled code, decompiled into macro instructions for a virtual machine, maybe something like Java.
 
  • #3
My guess is that it is compiled code, decompiled into macro instructions for a virtual machine, maybe something like Java.
I agree with Baluncore's assessment, but it doesn't appear to be either Java or Python bytecodes.

As a total guess,
txn might be a call to some function. I have done a websearch for this one and the txna instruction, and have come up empty.
bz probably means branch if <something, possibly the top of the stack> is zero.
bnz probably means branch if <something, possibly the top of the stack> is nonzero.
 
  • #4
It's a stack based language, like forth or postscript. this code:
Code:
int 0
txn ApplicationID
==
bz label1
int0 puts an int on the stack, with value 0.
Txn ApplicationID puts the, application id field of the current transaction. on the stack. (Everything on this virtual machine runs in the context of a transaction. An application call is a transaction)
== looks removes the 2 values at the top of the stack and puts a 1 on the stack if the values were equal.
bz label1 jump to label1 if the top of the stack is a non-zero number.
I don't quite qet variable scope, there's a global dictionary, which you can access with app_global_put and app_global_get. and local variables, which you can access with app_local_put/get, and also a scratch space which you can access with load/store.
There are lots of operations on byteblock. (cryptographic primitives, string operations)
While there is an excellent explanation of the virtual machine and opcodes here: https://developer.algorand.org/docs/get-details/dapps/avm/teal/opcodes/ the programs is unfortunately very hard to comprehend, mainly because all the jump labels have no meaningful names.
 
  • #5
bz label1 jump to label1 if the top of the stack is a non-zero number.
Wouldn't this be "jump to label1 if TOS is zero"?
 
  • #6
Wouldn't this be "jump to label1 if TOS is zero"?
Probably.
I guess == means compare TOS with NOS, maybe by simple subtract.
Then bz is Branch if TOS is Zero; bnz is Branch if TOS is NonZero.
 
  • #7
Thanks a lot people. Just to make sure I am not missing the gist of what is going on, the website that provides this code gives a decompiled code (called opcodes), it probably isn't the original code written by the programmers of the ''smart contract''. And this decompiled code can probably be understood with a lot of efforts (can it be ran? that would be a quick way to make sure it runs as intended).
 
  • #8
I think it is bytecode for the etherium vm
 
  • #9
Thanks a lot people. Just to make sure I am not missing the gist of what is going on, the website that provides this code gives a decompiled code (called opcodes), it probably isn't the original code written by the programmers of the ''smart contract''. And this decompiled code can probably be understood with a lot of efforts (can it be ran? that would be a quick way to make sure it runs as intended).

the code looks like teal

yes, it can be run.. you can modify it and run by your self.. search algorand teal in youtube if interested

there are people that write in this code.. it is quite simple mainly for the logicsig purposes, but there are higher level languages also for algo.. eg reach
 
  • #10
the code looks like teal

yes, it can be run.. you can modify it and run by your self.. search algorand teal in youtube if interested

there are people that write in this code.. it is quite simple mainly for the logicsig purposes, but there are higher level languages also for algo.. eg reach
Yeah, as been mentioned before here, this is Teal. And yes, I am aware of the new videos on youtube about it.
I didn't know about reach language though, thanks for letting me know.
 

Suggested for: How to understand this "decompiled" program?

Replies
13
Views
156
Replies
2
Views
776
Replies
2
Views
717
Replies
5
Views
522
Replies
4
Views
529
Replies
89
Views
3K
Replies
11
Views
549
Back
Top