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:
- Deport the computation logic in another contract and write an entrypoint that only set the value.
- Use a very opened entrypoint type.
- 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