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 toAdd(Add(Int(1), Int(2)), Int(3))
Int(1) + Int(2) * Int(3)
is equivalent toAdd(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"