The Standard

The Standard
DeFiHardhat
20,000 USDC
View results
Submission Details
Severity: low
Invalid

Unhandled chainlink revert would lock most funds

Summary

Chainlink’s multisigs can immediately block access to price feeds at will. Therefore, to prevent denial of service scenarios, it is recommended to query Chainlink price feeds using a defensive approach with Solidity’s try/catch structure. In this way, if the call to the price feed fails, the caller contract is still in control and can handle any errors safely and explicitly.

Vulnerability Details

Call to latestRoundData could potentially revert and make it impossible to query any prices. Feeds cannot be changed after they are configured in vaults (calculator is immutable)
https://github.com/Cyfrin/2023-12-the-standard/blob/91132936cb09ef9bf82f38ab1106346e2ad60f91/contracts/SmartVaultV3.sol#L24-L40

@> IPriceCalculator public immutable calculator;
address public owner;
uint256 private minted;
bool private liquidated;
event CollateralRemoved(bytes32 symbol, uint256 amount, address to);
event AssetRemoved(address token, uint256 amount, address to);
event EUROsMinted(address to, uint256 amount, uint256 fee);
event EUROsBurned(uint256 amount, uint256 fee);
constructor(bytes32 _native, address _manager, address _owner, address _euros, address _priceCalculator) {
NATIVE = _native;
owner = _owner;
manager = _manager;
EUROs = IEUROs(_euros);
@> calculator = IPriceCalculator(_priceCalculator);

https://github.com/Cyfrin/2023-12-the-standard/blob/91132936cb09ef9bf82f38ab1106346e2ad60f91/contracts/LiquidationPool.sol#L22-L39

@> address private immutable eurUsd;
address[] public holders;
mapping(address => Position) private positions;
mapping(bytes => uint256) private rewards;
PendingStake[] private pendingStakes;
address payable public manager;
address public tokenManager;
struct Position { address holder; uint256 TST; uint256 EUROs; }
struct Reward { bytes32 symbol; uint256 amount; uint8 dec; }
struct PendingStake { address holder; uint256 createdAt; uint256 TST; uint256 EUROs; }
constructor(address _TST, address _EUROs, address _eurUsd, address _tokenManager) {
TST = _TST;
EUROs = _EUROs;
@> eurUsd = _eurUsd;

See https://medium.com/cyfrin/chainlink-oracle-defi-attacks-93b6cb6541bf#e100 for more details

Impact

Already created Vaults are locked (burn, mint, swap, liquidate, removeCollateral, removeCollateralNative all call oracle)
Loss of funds because can't withdraw, can't liquidate, funds are locked on the contract

Proof of Concept

N/A

Tools Used

Manual review

Recommended Mitigation Steps

Surround the call to latestRoundData() with try/catch instead of calling it directly. In a scenario where the call reverts, the catch block can be used to call a fallback oracle or handle the error in any other suitable way.

Updates

Lead Judging Commences

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

chainlink-revert

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

chainlink-revert

Support

FAQs

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