BriVault

First Flight #52
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Impact: medium
Likelihood: medium
Invalid

Missing Emergency Pause and Rescue Mechanism

Root + Impact

Description

  • The contract lacks a pause or rescue mechanism to respond to emergencies

  • This makes it impossible for the owner to temporarily halt deposits/joins or safely withdraw locked assets in a critical scenario.

contract BriVault is ERC4626, Ownable {
@> // No `pause`, `unpause`, or `rescueTokens` functions defined.
@> // Critical vault actions like deposit(), joinEvent(), withdraw() cannot be stopped.
}

Risk

Likelihood:

  • The absence of a Pausable pattern affects every function there’s no mitigation in place once deployed.

  • While not immediately exploitable, this issue will manifest during unexpected token behavior or security incidents, where the lack of control prevents safe responses.

Impact:

  • If a bug or exploit is found after deployment, the team cannot pause or recover funds.

  • In case of ERC20 transfer failures or misbehavior, user funds may remain stuck forever.

Proof of Concept

Explanation:

When a security flaw or stuck asset situation occurs, the owner cannot react.
Even legitimate rescue attempts (like recovering wrong ERC20 tokens sent to the vault) will fail because the contract doesn’t have a mechanism for it.

function test_NoPauseMechanism() public {
// Simulate discovering a bug after launch
vm.prank(owner);
bool canPause = address(vault).code.length > 0; // contract deployed
// Owner cannot stop deposits or rescue tokens
vm.expectRevert();
vault.pause(); // function does not exist
vm.expectRevert();
vault.rescueTokens(address(asset), owner); // not implemented
}

Recommended Mitigation

Explanation:

  • pause() / unpause() allow the owner to freeze vault activity in emergencies.

  • rescueTokens() enables the recovery of tokens accidentally stuck in the contract.

  • nonReentrant ensures safety against reentrancy in deposit/withdraw flows

import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
-contract BriVault is ERC4626, Ownable {
+contract BriVault is ERC4626, Ownable, Pausable, ReentrancyGuard {
+ function pause() external onlyOwner {
+ _pause();
+ }
+ function unpause() external onlyOwner {
+ _unpause();
+ }
+ function rescueTokens(address token, address to) external onlyOwner {
+ uint256 amount = IERC20(token).balanceOf(address(this));
+ IERC20(token).transfer(to, amount);
+ }
function deposit(uint256 assets, address receiver)
public
override
+ whenNotPaused
+ nonReentrant
returns (uint256)
{
...
}
}
Updates

Appeal created

bube Lead Judge 21 days ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!