Globalget and globalput function in PyTeal and branching IF

Hi everybody,
I have a problem in a Smart Contract: because of some operations, I could have some negative values, so, to avoid this problem, for any operations, like x = v1-h I want the absolute value. So, using the function globalput and globalget, I tried this:

If(Lt(v1, h),
       App.globalPut(Bytes("negative"), Bytes("1")),
       App.globalPut(Bytes("negative"), Bytes("0"))
       )
negative = App.globalGet(Bytes("negative"))


If(Eq(negative, Bytes("1")),
       App.globalPut(Bytes("x"), h - v1),
       App.globalPut(Bytes("x"), v1 - h)
)
x = App.globalGet(Bytes("x"))

Where I check h = 1581 and v1 = 0, but negative = 0.
I tried this with Int(1) and Int(0) too instead of Bytes(“1”) and Bytes(“0”).

What’s the problem?

This is indeed strange.
Did you try to debug it step by step using dry run or tealdbg https://developer.algorand.org/docs/features/asc1/debugging ?

Through dryrun I get this error: invalid : 33 app_global_get not allowed in current mode.
I hope I’ve used dry run in the right way.

I wouldn’t use globalPut and globalGet is this task:

$ cat lt.py
from pyteal import *

def Abs_diff(a: Expr, b: Expr) -> TealType.uint64:
    return If (Lt(a, b), b-a, a-b)


abs_diff_1 = Abs_diff(Int(33), Int(22))
abs_diff_2 = Abs_diff(Int(55), Int(11))


a = ScratchVar(TealType.uint64)
b = ScratchVar(TealType.uint64)
abs_diff_3 = Abs_diff(a.load(), b.load())

program = Seq([
    Assert(abs_diff_1 == Int(11)),
    Assert(abs_diff_2 == Int(44)),
    a.store(Int(222)),
    b.store(Int(333)),
    Assert(abs_diff_3 == Int(111)),
    Int(1)
])

print(compileTeal(program, mode=Mode.Application, version=3))


$ cat comp.sh
#!/bin/bash

gcmd="~/n_test1/goal -d ~/n_test1/data_testnet"

python3 lt.py > lt.teal
CONTRACT_ADDR=`eval $gcmd clerk compile lt.teal | awk '{ print $2 }'`
echo "Contract address: $CONTRACT_ADDR"

eval $gcmd clerk send -f $CONTRACT_ADDR -t $CONTRACT_ADDR -a 0 -o tx0.tx
eval $gcmd clerk sign -p lt.teal -i tx0.tx -o stx0.tx
eval $gcmd clerk dryrun -t stx0.tx


$ ./comp.sh
Contract address: MMTL7BRLMSNRWMBGZ44PNZ76LIFFFUHYBCAWBO2ZSJ5LXEELGXNQD7OV6A
tx[0] cost=48 trace:
  1 intcblock => <empty stack>
 14 intc_0 => (33 0x21) 
 15 intc_1 => (22 0x16) 
 16 < => (0 0x0) 
 17 bnz => <empty stack>
 20 intc_0 => (33 0x21) 
 21 intc_1 => (22 0x16) 
 22 - => (11 0xb) 
 23 b 0x00 0x03 => (11 0xb) 
 29 intc_2 => (11 0xb) 
 30 == => (1 0x1) 
 31 assert => <empty stack>
 32 intc_3 => (55 0x37) 
 33 intc_2 => (11 0xb) 
 34 < => (0 0x0) 
 35 bnz => <empty stack>
 38 intc_3 => (55 0x37) 
 39 intc_2 => (11 0xb) 
 40 - => (44 0x2c) 
 41 b 0x00 0x03 => (44 0x2c) 
 47 intc 0x04 => (44 0x2c) 
 49 == => (1 0x1) 
 50 assert => <empty stack>
 51 intc 0x05 => (222 0xde) 
 53 store 0x00 => <empty stack>
 55 intc 0x06 => (333 0x14d) 
 57 store 0x01 => <empty stack>
 59 load 0x00 => (222 0xde) 
 61 load 0x01 => (333 0x14d) 
 63 < => (1 0x1) 
 64 bnz => <empty stack>
 75 load 0x01 => (333 0x14d) 
 77 load 0x00 => (222 0xde) 
 79 - => (111 0x6f) 
 80 intc 0x07 => (111 0x6f) 
 82 == => (1 0x1) 
 83 assert => <empty stack>
 84 intc 0x08 => (1 0x1) 

 - pass -

I realized that your code might not work because PyTEAL does not execute everything line by line.
Concretely, on @Maugli’s solution, if the last part of the PyTEAL program was:

print(compileTeal(abs_diff_3, mode=Mode.Application, version=3))

instead of

print(compileTeal(program, mode=Mode.Application, version=3))

then abs_diff_1 and abs_diff_2 would never be computed. And if they involved storing state, this state would never be stored.

Concretely, what argument did you give to compileTeal?

My code is in an approval_program function, so my last call is compiled = compileTeal(approval_program(), Mode.Application)

But what does your approval_program() look like? You can remove the parts you want to hide, but keep the general structure.