Limits on Btoi() in PyTEAL

Hey guys!

I’m trying to understand some of the PyTEAL functions better. According to the docs, the Btoi() function returns a uint64.

My question is: What would happen if one passed the bytes of a number with more than 21 digits (greater than 2^64) to Btoi? Would the transaction be automatically rejected because of this operation?

Here’s my sample code

# assume params/addresses/amt/key have been declared already

note = '12345678909876543210321'.encode()
PaymentTxn(address1, params, address3, amt, note=note).sign(key)

This signed txn is now paired with another txn signed by logic signed by address2. The PyTEAL logic is

def teal_prog():

    core = And(
        Global.group_size() == Int(2),
        Gtxn[0].type_enum() == TxnType.Payment,
        Gtxn[0].sender() == address1,
        Gtxn[0].receiver() == Gtxn[1].receiver(),
        Gtxn[1].type_enum() == TxnType.Payment,
        Gtxn[1].amount() == Btoi(Gtxn[0].note()) % 100000,
    return core

( address1 uses the note field to tell address2 how many algos they owe. For whatever reason, address1 didn’t realize their note field was so long! Luckily, address2 set a limit of 99999 microalgos )

What happens when address1 submits the two PaymentTxns (after signing with the LogicSig)?

Your example will not work because Btoi does not convert a string representing a number.
It takes as input a byte array representing a 64-bit number in big endian.
See How to convert "1" to 1 in Teal? - #2 by fabrice and Endianness - Wikipedia

1 Like

Is there an easier way to pass a number through the “note” field of a transaction? Like is this the best one can do:

note = '123'.encode()

I found another way to pass a note as a message pack, but I’m not sure if that makes TEAL conversion easier

import base64
from algosdk import encoding

note = base64.b64decode(encoding.msgpack_encode({"num":str(17772)}))

None of these options can easily be decoded using TEAL.

What you need to do is encode the number in big endian:

note = (123).to_bytes(8,'big')

Note that in the future, you may consider following the draft ARC: ARCs/ at main · algorandfoundation/ARCs · GitHub and prefix your note with myapplication:b. I.e.:

note = "myapplication:b".encode() + (123).to_bytes(8,'big')

Since it’s still a draft, it may change.

1 Like

Great work on those conventions! They sound like an excellent idea!

My only worry with following them is that they’ll complicate Btoi(txn.note()) operations.

Bringing this full circle to my original question, what would happen if I set

note = (123456789098765432100112).to_bytes(8,"big")

and then checked that against the PyTEAL logic

Gtxn[1].amount() == Btoi(Gtxn[0].note()) % 100000

(where the note is attached to the first transaction)

You can use the subtring opcodes to parse the note and remove the prefix.

btoi panic if the input is too long:

This means that the smart contract fails.

1 Like

Thank you so much! That was extremely helpful!