Integers and mutez
SmartPy has several types for integers: sp.nat
for non-negative integers, sp.int
for (all) integers, and sp.mutez
for non-negative amounts of micro-Tez, the token of the Tezos blockchain.
sp.int
and sp.nat
A literal integer such as 2
is either of type sp.nat
or sp.int
, depending on how it is used. In order to be explicit about the type, you can simply write sp.nat(2)
or sp.int(2)
.
Basic arithmetic
The operators +
, -
, *
and /
perform addition, subtraction, multiplication, and division, respectively. They are homogeneous, meaning that both arguments must be of the same type (either both sp.nat
or both sp.int
).
The type of the result is the same as the arguments, except for -
, which always returns an sp.int
.
Examples:
assert sp.nat(2) + sp.nat(3) == sp.nat(5)
assert sp.int(2) + sp.int(3) == sp.int(5)
assert sp.nat(2) - sp.nat(3) == sp.int(-1)
assert sp.int(2) - sp.int(3) == sp.int(-1)
The unary negation operator -
can take either sp.nat
or sp.int
and always returns an sp.int
. For example, - sp.nat(2) == sp.int(-2)
.
Mixing different types yields an error: for example sp.nat(2) + sp.int(3)
is invalid. For heterogeneous arguments there are sp.add
, sp.sub
, sp.mul
.
Example:
a = sp.nat(2)
b = sp.int(3)
assert sp.add(a, b) == sp.int(5)
Division
- sp.ediv(a: sp.nat, b: sp.nat) → sp.option[sp.pair[sp.nat, sp.nat]]
- sp.ediv(a: sp.int, b: sp.nat) → sp.option[sp.pair[sp.int, sp.nat]]
- sp.ediv(a: sp.nat, b: sp.int) → sp.option[sp.pair[sp.int, sp.nat]]
- sp.ediv(a: sp.int, b: sp.int) → sp.option[sp.pair[sp.int, sp.nat]]
sp.ediv
performs Euclidean division. Note that the result type depends on the types of the given arguments.The option catches division by zero:
sp.ediv(a, 0) == None
. Ifb != 0
, thensp.ediv(a, b) = sp.Some(q, r)
whereq
(the quotient) andr
(the remainder) are the unique integers such thata == q * b + r
and both0 <= r
andr < b
.Example:
smartpyassert sp.ediv( 14, 3) == sp.Some(( 4, 2)) # 14 == 4 * 3 + 2 assert sp.ediv(-14, 3) == sp.Some((-5, 1)) # -14 == -5 * 3 + 1 assert sp.ediv( 14,-3) == sp.Some((-4, 2)) # 14 == -4 * -3 + 2 assert sp.ediv(-14,-3) == sp.Some(( 5, 1)) # -14 == 5 * -3 + 1 (quotient, remainder) = sp.ediv(a, b).unwrap_some(error="Division by 0")
If a
and b
are of the same type quotient and remainder can be obtained as a / b
and sp.mod(a, b)
, respectively. In both cases a Division_by_zero
error is raised if b == 0
.
WARNING
For negative denominators the result of division differs between SmartPy and Python. SmartPy follows the Michelson semantics, whereas Python rounds the quotient towards negative infinity (yielding negative remainders!). To avoid confusion between the two, the SmartPy syntax uses /
and sp.mod
instead of //
and %
.
Comparison
Two integers of the same type (either sp.nat
or sp.int
) can be compared with the operators ==
, !=
, <
, <=
, >
, >=
. The result is of type sp.bool
. For example, 2 == 3
is False
.
From sp.nat
to sp.int
- sp.to_int(x: sp.nat) → sp.int
To convert from
sp.nat
tosp.int
, there issp.to_int
. For examplesp.to_int(sp.nat(2)) == sp.to_int(2)
, or (thanks to type inference)sp.to_int(2) == 2
.
From sp.int
to sp.nat
- sp.is_nat(a: sp.int) → sp.option[sp.nat]
sp.is_nat
takes ansp.int
and returns a value of typesp.option[sp.nat]
. Ifa >= 0
, thensp.is_nat(a) == sp.Some(b)
, whereb
is the uniquesp.nat
such thatsp.to_int(b) == a
(i.e.a
andb
represent the same integer). Ifa < 0
, thensp.is_nat(a) == None
. For example:smartpyassert sp.is_nat( 2) == sp.Some(2) assert sp.is_nat(-2) == None
- sp.as_nat(x: sp.int) → sp.nat
sp.as_nat
performs the same conversion, but instead of returning an option raises an error on negative numbers. Thussp.as_nat(2) == 2
, whereassp.as_nat(-2)
yields an error.
Bitwise arithmetic
Bitwise and, or and xor operations are available as &
, |
and ^
on sp.nat
:
assert 42 & 1 == 0
assert 42 | 1 == 43
assert 42 ^ 1 == 43
Furthermore, ~x
computes the two's complement of x
(of type sp.int
):
assert ~100 == -101
Shifting
Left and right shifts are also available as <<
and >>
on sp.nat
:
assert 42 << 1 == 84
assert 42 >> 1 == 21
Token amounts
Micro-Tez amounts are always prefixed by sp.mutez
, so e.g. sp.mutez(42)
denotes 42 micro-Tez, e.g. 0.000042
Tez. This expression is of type sp.mutez
.
sp.tez(a)
is equivalent to sp.mutez(a * 1_000_000)
.
Addition and subtraction on sp.mutez
can be performed with +
and -
. If subtraction were to yield a negative value, an error is raised instead. Thus sp.mutez(5) - sp.mutez(2) == sp.mutez(3)
, whereas sp.mutez(5) - sp.mutez(10)
yields an error.
- sp.split_tokens(amount: sp.mutez, quantity: sp.nat, division: sp.nat) → sp.mutez
For combined multiplication and division on
sp.mutez
values there issp.split_tokens(a, b, c)
, which calculates the value "a * b / c
".This enables the computation of mutez percentages, for example:
smartpysp.split_tokens(sp.mutez(200), 5, 100) == sp.mutez(10) # 5% of 200 mutez