Skip to content
On this page

Integers and mutez

SmartPy has several types for integers: sp.nat for non-negative integers, for (all) integers, and sp.mutez for non-negative amounts of micro-Tez, the token of the Tezos blockchain. and sp.nat

A literal integer such as 2 is either of type sp.nat or, depending on how it is used. In order to be explicit about the type, you can simply write sp.nat(2) or

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

The type of the result is the same as the arguments, except for -, which always returns an


assert sp.nat(2) + sp.nat(3) == sp.nat(5)
assert + ==
assert sp.nat(2) - sp.nat(3) ==
assert - ==

The unary negation operator - can take either sp.nat or and always returns an For example, - sp.nat(2) ==

Mixing different types yields an error: for example sp.nat(2) + is invalid. For heterogeneous arguments there are sp.add, sp.sub, sp.mul.


a = sp.nat(2)
b =
assert sp.add(a, b) ==


sp.ediv performs Euclidean division. If both of its arguments are of type sp.nat, its result type is sp.option[sp.pair[sp.nat, sp.nat]], otherwise sp.option[sp.pair[, sp.nat]].

The option catches division by zero: sp.ediv(a, 0) == None. If b != 0, then sp.ediv(a, b) = sp.Some(q, r) where q (the quotient) and r (the remainder) are the unique integers such that a == q * b + r and both 0 <= r and r < b.


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
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

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.


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 %.


Two integers of the same type (either sp.nat or can be compared with the operators ==, !=, <, <=, >, >=. The result is of type sp.bool. For example, 2 == 3 is False.

From sp.nat to

To convert from sp.nat to, there is sp.to_int. For example sp.to_int(sp.nat(2)) == sp.to_int(2), or (thanks to type inference) sp.to_int(2) == 2.

From to sp.nat

sp.is_nat takes an and returns a value of type sp.option[sp.nat]. If a >= 0, then sp.is_nat(a) == sp.Some(b), where b is the unique sp.nat such that sp.to_int(b) == a (i.e. a and b represent the same integer). If a < 0, then sp.is_nat(a) == None. For example:

assert sp.is_nat( 2) == sp.Some(2)
assert sp.is_nat(-2) == None

sp.as_nat performs the same conversion, but instead of returning an option raises an error on negative numbers. Thus sp.as_nat(2) == 2, whereas sp.as_nat(-2) yields an error.

Bitwise arithmetic

Bitwise and and or operations are available as | and & on sp.nat:

assert 42 & 1 == 0
assert 42 | 1 == 43

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 is sp.split_tokens(a, b, c), which calculates the value "a * b / c".

This enables the computation of mutez percentages, for example:

sp.split_tokens(sp.mutez(200), 5, 100) == sp.mutez(10)  # 5% of 200 mutez