Arithmetic Operations

An arithmetic expression is an expression that results in a TealType.uint64 value. In PyTeal, arithmetic expressions include integer and boolean operators (booleans are the integers 0 or 1). The table below summarized all arithmetic expressions in PyTeal.

Operator

Overloaded

Semantics

Example

Lt(a, b)

a < b

1 if a is less than b, 0 otherwise

Int(1) < Int(5)

Gt(a, b)

a > b

1 if a is greater than b, 0 otherwise

Int(1) > Int(5)

Le(a, b)

a <= b

1 if a is no greater than b, 0 otherwise

Int(1) <= Int(5)

Ge(a, b)

a >= b

1 if a is no less than b, 0 otherwise

Int(1) >= Int(5)

Add(a, b)

a + b

a + b, error (panic) if overflow

Int(1) + Int(5)

Minus(a, b)

a - b

a - b, error if underflow

Int(5) - Int(1)

Mul(a, b)

a * b

a * b, error if overflow

Int(2) * Int(3)

Div(a, b)

a / b

a / b, error if divided by zero

Int(3) / Int(2)

Mod(a, b)

a % b

a % b, modulo operation

Int(7) % Int(3)

Exp(a, b)

a ** b

a ** b, exponent operation

Int(7) ** Int(3)

Eq(a, b)

a == b

1 if a equals b, 0 otherwise

Int(7) == Int(7)

Neq(a, b)

a != b

0 if a equals b, 1 otherwise

Int(7) != Int(7)

And(a, b)

1 if a > 0 && b > 0, 0 otherwise

And(Int(1), Int(1))

Or(a, b)

1 if a > 0 || b > 0, 0 otherwise

Or(Int(1), Int(0))

Not(a)

1 if a equals 0, 0 otherwise

Not(Int(0))

BitwiseAnd(a,b)

a & b

a & b, bitwise and operation

Int(1) & Int(3)

BitwiseOr(a,b)

a | b

a | b, bitwise or operation

Int(2) | Int(5)

BitwiseXor(a,b)

a ^ b

a ^ b, bitwise xor operation

Int(3) ^ Int(7)

BitwiseNot(a)

~a

~a, bitwise complement operation

~Int(1)

Most of the above operations take two TealType.uint64 values as inputs. In addition, Eq(a, b) (==) and Neq(a, b) (!=) also work for byte slices. For example, Arg(0) == Arg(1) and Arg(0) != Arg(1) are valid PyTeal expressions.

Both And and Or also support more than 2 arguments when called as functions:

  • And(a, b, ...)

  • Or(a, b, ...)

The associativity and precedence of the overloaded Python arithmetic operators are the same as the original python operators . For example:

  • Int(1) + Int(2) + Int(3) is equivalent to Add(Add(Int(1), Int(2)), Int(3))

  • Int(1) + Int(2) * Int(3) is equivalent to Add(Int(1), Mul(Int(2), Int(3)))

Byteslice Arithmetic

Byteslice arithemetic is available for Teal V4 and above. Byteslice arithmetic operators allow up to 512-bit arithmetic. In PyTeal, byteslice arithmetic expressions include TealType.Bytes values as arguments (with the exception of BytesZero) and must be 64 bytes or less. The table below summarizes the byteslize arithmetic operations in PyTeal.

Operator

Return Type

Example

Example Result

BytesLt(a, b)

TealType.uint64

BytesLt(Bytes("base16", "0xFF"), Bytes("base16", "0xFE"))

0

BytesGt(a, b)

TealType.uint64

BytesGt(Bytes("base16", "0xFF"), Bytes("base16", "0xFE"))

1

BytesLe(a, b)

TealType.uint64

BytesLe(Bytes("base16", "0xFF"), Bytes("base16", "0xFE"))

0

BytesGe(a, b)

TealType.uint64

BytesGe(Bytes("base16", "0xFF"), Bytes("base16", "0xFE"))

1

BytesEq(a, b)

TealType.uint64

BytesEq(Bytes("base16", "0xFF"), Bytes("base16", "0xFF"))

1

BytesNeq(a, b)

TealType.uint64

BytesNeq(Bytes("base16", "0xFF"), Bytes("base16", "0xFF"))

0

BytesAdd(a, b)

TealType.Bytes

BytesAdd(Bytes("base16", "0xFF"), Bytes("base16", "0xFE"))

0x01FD

BytesMinus(a, b)

TealType.Bytes

BytesMinus(Bytes("base16", "0xFF"), Bytes("base16", "0xFE"))

0x01

BytesMul(a, b)

TealType.Bytes

BytesMul(Bytes("base16", "0xFF"), Bytes("base16", "0xFE"))

0xFD02

BytesDiv(a, b)

TealType.Bytes

BytesDiv(Bytes("base16", "0xFF"), Bytes("base16", "0x11"))

0x0F

BytesMod(a, b)

TealType.Bytes

BytesMod(Bytes("base16", "0xFF"), Bytes("base16", "0x12"))

0x03

BytesAnd(a, b)

TealType.Bytes

BytesAnd(Bytes("base16", "0xBEEF"), Bytes("base16", "0x1337"))

0x1227

BytesOr(a, b)

TealType.Bytes

BytesOr(Bytes("base16", "0xBEEF"), Bytes("base16", "0x1337"))

0xBFFF

BytesXor(a, b)

TealType.Bytes

BytesXor(Bytes("base16", "0xBEEF"), Bytes("base16", "0x1337"))

0xADD8

BytesNot(a)

TealType.Bytes

BytesNot(Bytes("base16", "0xFF00"))

0x00FF

BytesZero(a)

TealType.Bytes

BytesZero(Int(4))

0x00000000

Currently, byteslice arithmetic operations are not overloaded, and must be explicitly called.

Bit and Byte Operations

In addition to the standard arithmetic operators above, PyTeal also supports operations that manipulate the individual bits and bytes of PyTeal values.

To use these operations, you’ll need to provide an index specifying which bit or byte to access. These indexes have different meanings depending on whether you are manipulating integers or byte slices:

  • For integers, bit indexing begins with low-order bits. For example, the bit at index 4 of the integer 16 (000...0001000 in binary) is 1. Every other index has a bit value of 0. Any index less than 64 is valid, regardless of the integer’s value.

    Byte indexing is not supported for integers.

  • For byte strings, bit indexing begins at the first bit. For example, the bit at index 0 of the base16 byte string 0xf0 (11110000 in binary) is 1. Any index less than 4 has a bit value of 1, and any index 4 or greater has a bit value of 0. Any index less than 8 times the length of the byte string is valid.

    Likewise, byte indexing begins at the first byte of the string. For example, the byte at index 0 of that the base16 string 0xff00 (1111111100000000 in binary) is 255 (111111111 in binary), and the byte at index 1 is 0. Any index less than the length of the byte string is valid.

Bit Manipulation

The GetBit expression can extract individual bit values from integers and byte strings. For example,

GetBit(Int(16), Int(0)) # get the 0th bit of 16, produces 0
GetBit(Int(16), Int(4)) # get the 4th bit of 16, produces 1
GetBit(Int(16), Int(63)) # get the 63rd bit of 16, produces 0
GetBit(Int(16), Int(64)) # get the 64th bit of 16, invalid index

GetBit(Bytes("base16", "0xf0"), Int(0)) # get the 0th bit of 0xf0, produces 1
GetBit(Bytes("base16", "0xf0"), Int(7)) # get the 7th bit of 0xf0, produces 0
GetBit(Bytes("base16", "0xf0"), Int(8)) # get the 8th bit of 0xf0, invalid index

Additionally, the SetBit expression can modify individual bit values from integers and byte strings. For example,

SetBit(Int(0), Int(4), Int(1)) # set the 4th bit of 0 to 1, produces 16
SetBit(Int(4), Int(0), Int(1)) # set the 0th bit of 4 to 1, produces 5
SetBit(Int(4), Int(0), Int(0)) # set the 0th bit of 4 to 0, produces 4

SetBit(Bytes("base16", "0x00"), Int(0), Int(1)) # set the 0th bit of 0x00 to 1, produces 0x80
SetBit(Bytes("base16", "0x00"), Int(3), Int(1)) # set the 3rd bit of 0x00 to 1, produces 0x10
SetBit(Bytes("base16", "0x00"), Int(7), Int(1)) # set the 7th bit of 0x00 to 1, produces 0x01

Byte Manipulation

In addition to manipulating bits, individual bytes in byte strings can be manipulated.

The GetByte expression can extract individual bytes from byte strings. For example,

GetByte(Bytes("base16", "0xff00"), Int(0)) # get the 0th byte of 0xff00, produces 255
GetByte(Bytes("base16", "0xff00"), Int(1)) # get the 1st byte of 0xff00, produces 0
GetByte(Bytes("base16", "0xff00"), Int(2)) # get the 2nd byte of 0xff00, invalid index

GetByte(Bytes("abc"), Int(0)) # get the 0th byte of "abc", produces 97 (ASCII 'a')
GetByte(Bytes("abc"), Int(1)) # get the 1st byte of "abc", produces 98 (ASCII 'b')
GetByte(Bytes("abc"), Int(2)) # get the 2nd byte of "abc", produces 99 (ASCII 'c')

Additionally, the SetByte expression can modify individual bytes in byte strings. For example,

SetByte(Bytes("base16", "0xff00"), Int(0), Int(0)) # set the 0th byte of 0xff00 to 0, produces 0x0000
SetByte(Bytes("base16", "0xff00"), Int(0), Int(128)) # set the 0th byte of 0xff00 to 128, produces 0x8000

SetByte(Bytes("abc"), Int(0), Int(98)) # set the 0th byte of "abc" to 98 (ASCII 'b'), produces "bbc"
SetByte(Bytes("abc"), Int(1), Int(66)) # set the 1st byte of "abc" to 66 (ASCII 'B'), produces "aBc"