PyTeal App.localPut does not work as I expected

My code:

    Seq([
        Assert(
            Txn.application_args[0] == Bytes("b")
        ),
        App.localPut(Int(0), Bytes("T1"), Btoi(Txn.application_args[1])),
        App.localPut(Int(0), Bytes("T2"), Btoi(Txn.application_args[2])),
        Int(1)
    ])

Script:

export TOKEN1_INDEX="353"
export TOKEN2_INDEX="354"
goal app optin --app-id 310 --app-arg "str:b" --app-arg "str:${TOKEN1_INDEX}" --app-arg "str:${TOKEN2_INDEX}" --from "FKZGEODV5DEUZAEOHQKWUZL4W27LTRW45MQ6O5VDB4762EG23IRA2KCOKQ"

Result:

goal app read --app-id 310 --local --from FKZGEODV5DEUZAEOHQKWUZL4W27LTRW45MQ6O5VDB4762EG23IRA2KCOKQ
{
  "T1": {
    "tt": 2,
    "ui": 3354931
  },
  "T2": {
    "tt": 2,
    "ui": 3354930
  }
}

My expectation:

{
  "T1": {
    "tt": 2,
    "ui": 353
  },
  "T2": {
    "tt": 2,
    "ui": 354
  }
}

What am I doing wrong here? I’m new. Thanks in advance! :heart:

In the goal app call you’re specifying str: as the encoding, that means itll take the token index integer and convert it to bytes representing the string where each character is a byte (you want to specify int).

In the program logic you’re taking that string and trying to make it into an integer but btoi does not convert ASCII to int, it expects the 8 byte representation of a uint64.

When you read the state from the contract you get back a value corresponding to the decimal representation of what the uint64 value of those bytes from the string would be.

This is all solved by changing your app args to int to ensure they’re encoded correctly when passing them to the contract.

For reference:

2 Likes

Amazing! Thanks for quick and detailed answer bro. It works!