I have written a stateless teal contract which can opt in to a particular asset. However what stops someone from continually opting in to the same asset such that the contract account had to pay the transaction fee every time?
This is indeed an issue if you allow any opt-in transaction.
You need to modify the smart contract to prevent that.
The simplest solution is to require the opt-in transaction to have specific first valid round, last valid round, and lease.
For lease, see Algorand Developer Portal
Thanks @fabrice, I didn’t know about leases. Just to confirm my understanding:
- Would I hardcode a lease value into the smart contract which I would verify is used when opting into an asset?
- Would I set the last valid round to max value such that it can never be exploited?
- How do you choose the lease? Can it just be any value?
Reading the documentation it also mentions a denial of service attack on a smart contract, how does this relate? I presume this is not relevant to a stateless smart contract since it doesn’t live on the blockchain. What about with a stateful contract?
Here you find a TEAL example to securely handle ASA Opt-In in Stateless ASC1.
The ASC1 allow Opt-In transactions for a specific Asset ID submitted whitn a certain block, so nobody can burn Smart Contract funds with Opt-In after that block.
Thanks @cusma for the example. I think leases would be better though as it guarantees that you will only ever opt in once. Although practically it is probably the same unless someone can predict a stateless contract in advance and manage to submit many transactions in the small time frame.
You may also fund the account just with the minimum balance with an Atomic Transfer that includes the Opt-In transction and then add more fund to the Contract Address once the Opt-In validity block expired. In this case using the Lease could be an overkill.
- Yes, hardcode the lease value. Any non-zero value is good.
- Yes, you need to ensure last valid round is a fix given value. You don’t need to check for first valid round (but you can if you want).
- Just choose an arbitrary value, random, or your favorite 32-byte number.
The lease window is max 1000 rounds so I cannot just set it to a round say 50 years from now. I presume the solution is to also require the asset opt in to be before the last valid round round. Is there an alternative to this?
The lease is taken when the transaction is committed and released after the last valid round.
In case you cannot compute in advance the last valid round you want (e.g., if it’s in 50 years), you will need to combine your stateless contract with a stateful application,
The stateless contract will require to be called in a group with the stateful application.
The stateful application can check if an asset is already opt-in or not and approve the stateless TEAL transaction accordingly.