Why is the default approach to accept tez instead of refusing them like what we see in languages like Solidity or Vyper?
User can mistakenly send tez along with a contract call that does not require any coin, and if the contract does not check or does not have a cashback functionality, those funds are forever locked in the contract.
Instead of putting the burden on developers to make sure they don’t accept tez when unnecessary, would it not be more straightforward to have something like a decorator when the developer has decided that a specific entrypoint needs to receive tez?
Basically, “payable” in Solidity.
What was the reason that brought SmartPy to take the opposite approach?
Thanks for any reply
Thank you for your question.
What was the reason that brought SmartPy to take the opposite approach?
The design decision in SmartPy likely mirrors that of Michelson, the underlying Tezos smart contract language. The inherent similarities between smart contracts and implicit accounts (tz addresses) in Tezos might have driven Michelson’s choice. For a definitive reason on Michelson’s choice, I recommend raising the question on Tezos Agora.
Can SmartPy change its approach?
There have been suggestions to change this design. In the past, SmartPy considered a flag to indicate that a contract doesn’t allow Tez by default. I even worked on a decorator system for an older version to achieve the ‘payable’ functionality you referenced from Solidity.
However, making this change is challenging, given that the community is accustomed to the existing design.
The topic is still open. Feel free to make more suggestions in this theme.
Hi Jordan, thank you for your answer. I figured that would be the reason.
When coding with Ligo is easier, as you can just check for sent tez at the start of the main function, if you do not want your whole contract to accept tez. However, it isn’t any better if you want to have some entrypoints that accept tez and some that do not, so I thought both languages derived this approach from Michelson.
However, from a security standpoint, I think it would make sense to go with this change. Using a decorator seems like the best solution to me, as it is equivalent to the “payable” solution mentioned. I do understand that the community is accustomed to this behavior and there is a risk that compiling old contracts after this change might cause mayhem, but I think implementing a compiler warning if no “payable” decorator is present in the whole contract should prevent this risk.
For example, if the whole contract does not contain any “payable” decorator, the compiler could return a message along the lines of “This smart contract does not accept tez. Please refer to documentation XXX if you wish to accept tez payments”. This might be sufficiently clear.
What are your thought with regard to this?