0
Error: Uncaught (in promise) TezosOperationError: (temporary) proto.017-PtNairob.tez.subtraction_underflow

I know this error is caused by a subtraction resulting in a negative number, but i'm just trying a simple code and can't avoid this. My code: import smartpy as sp

FA2 = sp.io.import_script_from_url("https://legacy.smartpy.io/templates/fa2_lib.py")

class Token(FA2.Admin, FA2.MintFungible, FA2.Fa2Fungible):
    def __init__(self, admin, **kwargs):
        FA2.Fa2Fungible.__init__(self, **kwargs)
        FA2.Admin.__init__(self, admin)

class Marketplace(sp.Contract):
    def __init__(self, token, metadata, admin):
        self.init(
            token=token,
            metadata=metadata,
            admin=admin,
            data = sp.big_map(
                tkey=sp.TNat,
                tvalue=sp.TList(
                    sp.TRecord(
                        holder=sp.TAddress,
                        author=sp.TAddress,
                        amount=sp.TMutez,
                        token_id=sp.TNat,
                        editions=sp.TNat,
                        collectable=sp.TBool))),
            token_id=0)
    @sp.entry_point
    def send(self, params):
        total_price = sp.utils.nat_to_tez(params.total_price)
        sp.send(params.account, sp.split_tokens(total_price, 90, 100))

In front-end, i call like this:

...
const op = await contract.methods.send(accountx, 100000).send(100000)
...

Where the 100000 is what i'm trying to send and accountx is account to send.

2 Answers 2

0

As pointed by ojuswi-rastogi, the error you're seeing arises from the use of sp.send, as it attempts to send 90000 tez instead of mutez. This is because you're converting the input of 100000 (of type nat) to tez using sp.utils.nat_to_tez().

Instead of this conversion, it would be more appropriate to use the mutez type directly. However, I'd advise against using a parameter to specify the number of tez sent to your entry point. The reason is, a sender could specify any arbitrary number, which might not correspond to the actual amount sent.

Instead, you should utilize sp.amount, which gives you the exact number of mutez sent to the entry point. Here's a modified version of your code:

@sp.entry_point
def send(self, param):
    sp.send(params.account, sp.split_tokens(sp.amount, 90, 100))
-1

It's easier to debug it if you write some SmartPy tests for it. So, here you go:

@sp.add_test(name = 'Test')
def test():
    admin = sp.test_account('admin')
    sc = sp.test_scenario()

    token = Token(
        admin = admin.address,
        metadata = sp.big_map({"": sp.bytes('0x')})
    )
    sc += token

    marketplace = Marketplace(
        token = token.address,
        metadata = sp.big_map({"": sp.bytes('0x')}),
        admin = admin.address
    )
    sc += marketplace

    token.set_administrator(marketplace.address).run(sender = admin.address)

    marketplace.send(
        account = admin.address,
        total_price = 100000
    ).run(sender = admin.address, amount = sp.mutez(100000))

The error is coming at sp.send because it is trying to send 90000 tez instead of mutez. This is happening because we are sending 100000 nat, which is converted to 100000 tez using sp.utils.nat_to_tez(). So, the easiest solution is use nat_to_mutez instead of nat_to_tez. Like this:

total_price = sp.utils.nat_to_mutez(params.total_price)

Also, I'm not aware of your entire use case. But, you may also check sp.amount (Link) which you can use to get the amount of mutez that is sent to the contract in a transaction.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.