How to understand this "decompiled" program?

In summary, the website shows a "smart contract" that provides rewards to "stakers" for holding a particular token. The rewards are in the form of two different tokens. Usually, people who want to join the "staking pool" have to agree to the contract and then look at the code.
  • #1
fluidistic
Gold Member
3,923
261
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.
 
Technology news on Phys.org
  • #2
My guess is that it is compiled code, decompiled into macro instructions for a virtual machine, maybe something like Java.
 
  • #3
Baluncore said:
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.
 
  • Like
Likes .Scott
  • #5
willem2 said:
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
Mark44 said:
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
fluidistic said:
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
Scholtz said:
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.
 

1. What does it mean to "decompile" a program?

Decompilation refers to the process of converting a compiled program, which is written in a high-level programming language, back into its original source code. This can be useful for understanding how a program works or making changes to it.

2. How can I determine the original programming language used in a decompiled program?

There are a few ways to determine the original programming language of a decompiled program. One way is to look for common syntax and keywords used in that language. Another way is to analyze the assembly code, which can provide clues about the original language.

3. Can I modify a decompiled program and recompile it?

Technically, yes, it is possible to modify a decompiled program and recompile it. However, this is not recommended as it can be challenging to ensure the code is properly functioning and there may be legal implications for modifying someone else's code without permission.

4. Are there any limitations to decompiling a program?

Decompilation is not a perfect process, and there are some limitations. For example, some information may be lost during the compilation process, making it difficult to recover in the decompiled code. Additionally, some code may be obfuscated, which can make it more challenging to understand.

5. Can decompiling a program be illegal?

It depends on the specific circumstances. In some cases, decompiling a program may be considered a violation of intellectual property laws, especially if the program is protected by copyright. It is important to seek permission from the program's owner before attempting to decompile it.

Similar threads

  • Engineering and Comp Sci Homework Help
Replies
7
Views
2K
  • Programming and Computer Science
Replies
12
Views
1K
  • Programming and Computer Science
Replies
19
Views
979
  • Programming and Computer Science
Replies
1
Views
1K
  • Programming and Computer Science
Replies
4
Views
2K
  • Programming and Computer Science
Replies
5
Views
5K
  • Engineering and Comp Sci Homework Help
Replies
5
Views
2K
  • Programming and Computer Science
Replies
2
Views
3K
  • Programming and Computer Science
Replies
4
Views
3K
  • Programming and Computer Science
Replies
2
Views
316
Back
Top