2

I am trying to do some maths operations inside an on-chain view and am getting an unexpected result.

The reproduction contract tries to perform the following steps:

  1. Define an internal contract property of type nat (e.g. 40)
  2. Define a new local variable A of type nat inside the view (e.g. 1000)
  3. Multiply the internal nat value by 10 and store its result in another local variable B (will be 400)
  4. Subtract variable B from variable A (result is 600) and store result in another local variable C
  5. Divide variable C by 2 storing it in variable D and return the value (should return 300)
import smartpy as sp

class MathsTest(sp.Contract):
    def __init__(self, **kargs):
        self.init(
            internal_number=sp.nat(40),
            **kargs
        )

    @sp.onchain_view()
    def nat_test(self):
        maxi = sp.local('maxi', sp.nat(1000))
        multi = sp.local('multi', self.data.internal_number * sp.nat(10))
        sub = sp.local('sub', maxi.value - multi.value)
        div = sp.local('div', sub.value // sp.nat(2))

        sp.result(div.value)

@sp.add_test(name = "MathsTest")
def test():
    scenario = sp.test_scenario()
    scenario.h1("Maths")
    c1 = MathsTest()
    scenario += c1

    scenario.verify(c1.nat_test() == sp.nat(300))

Instead of passing the test throws the following:

Error: Type Error
Type sp.TInt / sp.TNat mismatch
Type Error (maxi.value : sp.TNat), (multi.value : sp.TNat) cannot be subtracted in (maxi.value - multi.value : sp.TNat)
(__main__, line 14)

Why does it say there is an int mismatch when everything is declared as nat?


Contract SmartPy Link

1 Answer 1

3

Subtractions are implicitly taken as int due to the possibility of negative results. Therefore, the variable sub is of type int here.

To resolve this, wrap sub as sp.as_nat(sub) on the dividend.

4
  • thank you. it's interesting that the error shows it is on line 14, the subtraction, when it is actually on line 15, the division
    – 0x10
    May 27, 2022 at 4:25
  • 2
    This is because SmartPy infers types for variables (local or storage) by finding references of the variable throughout the code. So, here sub was in line 14 but the type is inferred from line 15 because only a nat can be divided by another nat. May 27, 2022 at 5:20
  • 1
    Ints can be divided by nats too. Does it work with sp.int(300) instead of sp.nat(300) at the last line? Jun 9, 2022 at 12:26
  • 2
    @RaphaëlCauderlier Smartpy gives a straight-up type mismatch error when pairing ints and nats with any arithmetic operator. I didn't know it's allowed in Michelson. Jun 10, 2022 at 13:12

Your Answer

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

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