Int / nat / mutez casting

The following question has been asked on Telegram:

hihi, Trying to calculate a value and send that in tez:

        @sp.entrypoint
        def execute(self, price):
            address = sp.address('myAddress')
            fee = price * 1 / 100
            sp.send(address, sp.tez(fee))

I get the following error : sp.tez is undefined or wrong number of arguments
What am I missing? It works fine when I replace by: sp.send(address, sp.tez(2))

sp.tez is for literal values, e.g. sp.tez(42). You can use sp.split_tokens instead:

    @sp.entrypoint
    def execute(self, price):
        address = sp.address('myAddress')
        fee = sp.split_tokens(price, 1, 100)
        sp.send(address, fee)
1 Like

The error you’re encountering is because sp.tez(X) is not meant for converting X from sp.int or sp.nat to sp.mutez. Instead, it creates a sp.mutez value of X * 1_000_000.

Here’s the corrected version of your entrypoint:

        @sp.entrypoint
        def execute(self, price):
            sp.cast(price, sp.mutez)
            address = sp.address('myAddress')
            fee = sp.split_tokens(price, 1, 100)
            sp.send(address, fee)

How to convert X from sp.nat to sp.tez and why you should avoid that.

If you need to convert from sp.nat to sp.mutez or vice versa, you can use the utils module with methods like utils.mutez_to_nat, utils.nat_to_mutez or utils.nat_to_tez.

  1. Import the module: from utils import utils.

  2. Add it to the test scenario: sc = sp.test_scenario([utils, main]).

Here’s an example:

import smartpy as sp
from utils import utils

@sp.module
def main():
    class MyContract(sp.Contract):
        def __init__(self):
            self.data.x = utils.nat_to_mutez(5)

        @sp.entrypoint
        def ep(self):
            pass

if "templates" not in __name__:
    @sp.add_test(name="MyContract")
    def test():
        sc = sp.test_scenario([utils, main])
        c1 = main.MyContract()
        sc += c1
        c1.ep()

:warning: However, frequently needing these conversions may indicate improper type use. In Tezos, it’s generally preferred to manipulate values directly in the sp.mutez type. Hence, all parameters or storage values referring to XTZ tokens should ideally use the sp.mutez type.

Remember, passing a parameter like sp.tez(42) to an entrypoint doesn’t equate to sending 42 tez. It’s merely a mutez type value of 42’000’000.

1 Like

You can still create tez values with sp.tez(X).

For example:

import smartpy as sp

@sp.module
def main():
    class MyContract(sp.Contract):
        def __init__(self):
            pass

        @sp.entrypoint
        def execute(self, price):
            sp.cast(price, sp.mutez)
            fee = sp.split_tokens(price, 1, 100)
            sp.send(sp.sender, fee)

if "templates" not in __name__:
    @sp.add_test(name="MyContract")
    def test():
        sc = sp.test_scenario(main)
        c1 = main.MyContract()
        sc += c1
        alice = sp.test_account("alice")
        # Here you give tez value as parameter.
        c1.execute(sp.tez(42)).run(sender=alice)