The contract’s transactions
array grows indefinitely as new transactions are submitted. There is no built-in mechanism to remove or clean up older transactions, which may lead to a large on-chain data footprint and potential UI/UX complications over time.
Unbounded Array Growth:
The transactions
array is appended to on every submitTransaction
, and these entries remain in storage indefinitely.
If the contract is used frequently, the storage cost and gas usage for reading or iterating over transactions
grows significantly.
Lack of Cleanup or Archival Mechanism:
There is no function to remove or archive completed (executed) or outdated transactions.
The ever-increasing size of the array can cause maintenance issues and significantly inflate the contract’s on-chain data.
Potential DoS and UI/UX Impact:
Functions that iterate over a large array can become extremely expensive or fail due to out-of-gas errors.
On the front-end, if an application attempts to read the entire transactions
array via RPC, the query can exceed the maximum data size limit, causing calls to fail or slow down, degrading the user interface.
Front-End / UI Failures: Large data responses can break user interfaces or exceed RPC response size limits, preventing users from viewing the transaction list.
High Storage and Gas Costs: An ever-growing array increases on-chain state, making every interaction more expensive over time.
Manual Code Review: Observed that transactions
is never pruned or cleared after execution.
Implement a Cleanup / Archival Function:
Add a function to remove or archive old transactions (especially those already executed) to keep the on-chain array size manageable.
Consider off-chain indexing or event-based tracking for older transaction data.
Use a Mapped Storage Structure:
Consider using a mapping (e.g., mapping(uint => Transaction)
) with an incremental ID. This way, individual entries can be cleaned up or overwritten, reducing unbounded growth.
Minimize or Avoid Full Iterations:
Design workflows so that owners call specific transaction IDs rather than iterating through the entire list, limiting the risk of out-of-gas or heavy RPC responses.
Plan for Front-End Pagination:
If storing a large transaction history is unavoidable, ensure your UI or any off-chain service fetches and displays data in pages rather than pulling the entire array at once. This mitigates UI-breaking RPC data limits.
Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelyhood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.