1

I have a requirement where I need to pass a byte into a function and that function should convert that byte to integer and returns true if it is negative else false. the function will be this in the new syntax of smartpy.

        @sp.entrypoint
        def check_negative(self, x):
            self.data.is_negative = sp.to_int(x) < 0

But As I am using old syntax for writing a contract, How can I perform this computation .

I also tried deploying a contract with new syntax and writing above function on onchain_view and then calling that view from the contract with old syntax. It didn't work too.

Can anyone help me here?

3 Answers 3

1

It is available in the alpha of SmartPy 18.1. Here is an example:

import smartpy as sp

@sp.module
def main():
    class C(sp.Contract):
        def __init__(self):
            self.data.is_negative = False

        @sp.entrypoint
        def check_negative(self, x):
            self.data.is_negative = sp.to_int(x) < 0

@sp.add_test(name = "test")
def test():
    scenario = sp.test_scenario(main)
    c = main.C()
    scenario += c
    c.check_negative(sp.bytes("0x09"))
    scenario.verify(c.data.is_negative == False)
    c.check_negative(sp.bytes("0xf6"))
    scenario.verify(c.data.is_negative == True)
    c.check_negative(sp.bytes("0x00f6"))
    scenario.verify(c.data.is_negative == False)

Here is a workaround for the legacy syntax (notice that it doesn't work in the test scenario but you can originate the contract, you may use meta-programmation to mock it in scenario if you need):

to_int = sp.unpack(sp.constant(
            "expru2UfuHkkPH6UHCZyYuLU6BdmNhuksJkTbtAB1C1vVXiFQ9R1Ed",
            t = sp.TBytes), sp.TLambda(sp.TBytes, sp.TInt)).open_some()

Example:

import smartpy as sp

class Test(sp.Contract):
    def __init__(self, in_scenario):
        self.init(is_negative=False)
        self.in_scenario = in_scenario

    @sp.entrypoint
    def check_negative(self, x):
        to_int = sp.unpack(sp.constant(
            "expru2UfuHkkPH6UHCZyYuLU6BdmNhuksJkTbtAB1C1vVXiFQ9R1Ed",
            t = sp.TBytes), sp.TLambda(sp.TBytes, sp.TInt)).open_some()
        self.data.is_negative = to_int(x) < 0

if "templates" not in __name__:
    @sp.add_test(name = "Test")
    def test():
        c1 = Test(True)
        scenario = sp.test_scenario()
        scenario += c1
1

Direct conversion from bytes to int has been added to michelson in the latest protocol upgrade (mumbai). Release notes

Unfortunately, I do not think SmartPy supports these instructions yet. In the meanwhile you can adapt the Nat.of_bytes function to support decoding to int, you need to handle 2's complement.

Also, do you really need this? Is a really odd thing to do inside a smart-contract.

1

You can pass the bytes that are formed using sp.pack. And, parse the argument using sp.unpack. Here is the legacy documentation for that.

For example, it will look something like this in the legacy syntax:

import smartpy as sp

class Test(sp.Contract):
    def __init__(self):
        self.init(is_negative = False)

    @sp.entry_point
    def check_negative(self, num_bytes):
        num = sp.unpack(num_bytes, sp.TInt).open_some('unpack failed to parse integer')
        is_negative = num < 0
        self.data.is_negative = is_negative


@sp.add_test(name = "Test")
def test():
    scenario = sp.test_scenario()
    c = Test()
    scenario += c

    # Test with a positive integer
    scenario += c.check_negative(sp.pack(42))
    scenario.verify(c.data.is_negative == False)

    # Test with a negative integer
    scenario += c.check_negative(sp.pack(-42))
    scenario.verify(c.data.is_negative == True)

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.