1

I am using lazify=True to upgrade the function logic, I am wondering if there is a way lazify can help in upgrading the parameters too.

Can we update the following function

@sp.entry_point(lazify = True)
    def f1(self):
      pass

with the following code

def f1(self, x , y):
    self.data.token_price = x + y

here i am trying to replace old function with new function with same name but taking two parameters . Is this possible?

2 Answers 2

1

It is not possible to change the type of a contract. As a consequence it's not possible to change the number of parameters nor their types.

Tldr workarounds:

  1. Deport the computation logic in another contract and write an entrypoint that only set the value.
  2. Use a very opened entrypoint type.
  3. Use bytes as the entrypoint type. It will contain the pack of the value.

Detailed answer:

1) Deport the computation logic in another contract

In your contract you only set the token price and the address who can change it. In another contract you do the logic.

Example:

import smartpy as sp

class MyContract(sp.Contract):
    def __init__(self, price_setter):
        self.init(token_price=0, price_setter=price_setter)

    @sp.entry_point
    def set_token_price(self, token_price):
        sp.verify(sp.sender == self.data.price_setter)
        self.data.token_price = token_price

    @sp.entry_point
    def set_price_setter(self, new_price_setter):
        sp.verify(sp.sender == self.data.price_setter)
        self.data.price_setter = new_price_setter

class MyLogicContract(sp.Contract):
    @sp.entry_point
    def f1(self, x , y, destination):
        token_price = x + y
        sp.transfer(token_price, sp.tez(0), destination)

    @sp.entry_point
    def set_price_setter(self, new_price_setter, destination):
        sp.transfer(new_price_setter, sp.tez(0), destination)

When you want to upgrade your price setting logic you originate a new logic contract and call set_price_setter on the old to do the upgrade.

You can mix lazify and this technique if you want to originate contract only when you must do it.

2) Use a very opened entrypoint type.

With a map you are not limited in term of numbers of parameters. With a variant you can define multiple types allowed.

Example:

@sp.entry_point(lazify = True)
def f1(self, params):
    sp.set_type(
        params,
        sp.TMap(
            sp.TString,
            sp.TVariant(
                nat=sp.TNat,
                int=sp.TInt,
                string=sp.TString,
                bytes=sp.TBytes,
                mutez=sp.TMutez,
                bool=sp.TBool,
                address=sp.TAddress,
                timestamp=sp.TTimestamp
            )
        )
    )
    # ... here your logic
    # for example
    x = params["x"].open_variant("nat")
    y = params["y"].open_variant("nat")
    self.data.token_price = x + y

3) Use bytes as the entrypoint type.

Using bytes is a poor way to achieve your goal but it's the simplest way and it works.

You'll pack data before sending and unpack them in the entrypoint logic.

@sp.entry_point(lazify = True)
def f1(self, params):
    x, y = sp.match_pair(
        sp.unpack(
            params,
            sp.TPair(sp.TNat, sp.TNat).open_some()
        ))
    self.data.token_price = x + y
1

No, the function(entrypoint) signature cannot be modified once the contract has been deployed.

To support arbitrary inputs the function argument should be of type bytes. Then the upgradable lambda function is responsible for decoding those bytes to any structure.

Use sp.pack for encoding the structure and sp.unpack for decoding it.

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.