FA1.2 token spender gas issue
After several reviews of FA1.2 token compliant contracts, the team at Inference has identified a potential source of issues for users of this kind of contracts, which is detailed in the following paragraph. A possible solution to the problem is also suggested at the end of this blog post, in order to improve the overall security posture of the Tezos ecosystem.
The Tezos FA1.2 specification TZIP-007 defines that “spenders”, who are permitted to transfer tokens on behalf of the token owner, must be registered within a MAP data type called “allowances”.
Storing values in data types like MAP or SET carries the risk that, if they grow without bounds, the data may become unloadable due to defined blockchain constants, especially gas and storage limits, which restrict the effective size of a smart contract.
As of the current Tezos blockchain constants, we estimate that in a very basic FA1.2 token contract, the allowance map can accommodate approximately one million spenders before it exceeds the defined gas limits and becomes unloadable.
The allowance map is stored in the user’s ledger, represented as a BIG_MAP data type. Since big map entries are loaded on demand (lazily), an excessively large allowance map from a user won’t compromise the entire smart contract. Instead, it will only affect the particular user, leading to their tokens becoming locked within the smart contract.
It's worth noting that the FA1.2 standard permits only one spender per "approve" call entrypoint, and there's the possibility that the FA1.2 implementation may remove entries from the allowance MAP once they've been used. Given these constraints, the registration of around one million spenders appears highly unlikely.
While this scenario is indeed an unlikely edge case, we cannot predict how users of the smart contract will utilize these features. There is a potential that it could impact a user of the smart contract at some point, resulting in the permanent lockup of their tokens within the smart contract.
Hence, we advise smart contract developers to impose a restriction on the quantity of spenders within the allowance map.
Altering the storage design disrupts compatibility with the standard, potentially leading to complications with other components that support FA1.2 smart contracts, such as explorers, indexers, programming libraries, and more.
Thus, we propose updating the FA1.2 specification TZIP-007 to permit the storage of permitted spenders in a design that is not susceptible to potential gas-related problems. One possible approach is to segregate allowances from the user's ledger:
- big_map %ledger address nat
- big_map %allowances (pair address address) nat
If you are planning to develop a smart contract solution, or you already have one implemented, we recommend you have your solution audited to identify exposure to the detailed issue and other possible risks. If you wish for Inference to review your smart contracts, send us an email at [email protected] to get a quote for your audit!