The emergencyPauseAll
function iterates over the _authorizedContracts
set using its current length. If an admin removes a contract during this iteration, the loop may access an invalid index, causing the entire transaction to revert. This allows a malicious or compromised admin to prevent the emergency pause from completing, undermining the contract's emergency response mechanism.
Create a snapshot of the authorized contracts list before iterating. Store the current list in memory array at the start of the function and iterate over that array instead of the live set. This ensures that changes during execution do not affect the loop.
Line 131 – 144
When a contract is deauthorized via deauthorizeContract
, its isPaused
state remains unchanged. If the contract was paused prior to deauthorization, there is no way to unpause it afterward since unpauseContract
requires the contract to be authorized, resulting in permanent pause. Additionally, if the contract is later re-authorized, it retains its previous paused state, leading to unexpected behavior where the contract remains paused without explicit action. This can cause operational issues and disrupt protocol functionality indefinitely.
Reset the isPaused
state to false when deauthorizing a contract. Modify deauthorizeContract
to set isPaused[contractAddress] = false
before removing from the authorized set.
Line 141 – 154
The emergencyPauseAll
function iterates through all authorized contracts in a single transaction. If the number of authorized contracts is too large, the function may exceed the block gas limit, preventing the emergency pause from executing. This could leave the system vulnerable during critical situations.
Implement a paginated or batched approach for the emergency pause function, allowing it to process contracts in chunks to stay within gas limits. Alternatively, enforce a maximum limit on the number of authorized contracts.
Line 131 – 144