SCWE-146: Improper Use of try/catch Leading to Silent Failures
Stable Version v1.0
This content is in the version-(v1.0) and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).
Relationships¶
- CWE-390: Detection of Error Condition Without Action
https://cwe.mitre.org/data/definitions/390.html
Description¶
Solidity 0.6+ try/catch allows catching reverts from external calls. If the catch block does not properly handle the failure—e.g., proceeds without reverting, leaves state inconsistent, or swallows the error without logging—the contract can continue execution under incorrect assumptions. Silent failures can lead to fund loss, corrupted state, or exploitable inconsistencies.
Remediation¶
- In catch blocks, either revert with a clear message or update state to reflect the failure (e.g., mark operation as failed, emit event).
- Avoid proceeding with critical logic when the external call failed unless the failure is explicitly handled and documented.
Examples¶
Vulnerable¶
pragma solidity ^0.8.0;
contract Aggregator {
function swap(address router, bytes calldata data) external {
try IRouter(router).swap(data) returns (uint256 amountOut) {
transferToUser(msg.sender, amountOut);
} catch {
// Silent: user gets nothing but tx succeeds; state may be inconsistent
}
}
}
Fixed¶
function swap(address router, bytes calldata data) external {
try IRouter(router).swap(data) returns (uint256 amountOut) {
transferToUser(msg.sender, amountOut);
} catch {
revert("Swap failed");
}
}
catch (bytes memory reason) with string concatenation—reason may be a custom error selector, not a string.