28973 - [SC - Insight] Users CDPs can be removed unintentionally by CD...
Submitted on Mar 3rd 2024 at 21:16:50 UTC by @savi0ur for Boost | eBTC
Report ID: #28973
Report type: Smart Contract
Report severity: Insight
Target: https://github.com/ebtc-protocol/ebtc/blob/release-0.7/packages/contracts/contracts/SortedCdps.sol
Impacts:
Permanent freezing of funds
Description
Bug Description
https://github.com/ebtc-protocol/ebtc/blob/a96bd000c23425f04c3223a441a625bfb21f6686/packages/contracts/contracts/SortedCdps.sol#L420-L455
function batchRemove(bytes32[] memory _ids) external override {
_requireCallerIsCdpManager();
uint256 _len = _ids.length;
require(_len > 1, "SortedCdps: batchRemove() only apply to multiple cdpIds!");
bytes32 _firstPrev = data.nodes[_ids[0]].prevId;
bytes32 _lastNext = data.nodes[_ids[_len - 1]].nextId;
require(
_firstPrev != dummyId || _lastNext != dummyId,
"SortedCdps: batchRemove() leave ZERO node left!"
);
for (uint256 i = 0; i < _len; ++i) {
require(contains(_ids[i]), "SortedCdps: List does not contain the id");
}
// orphan nodes in between to save gas
if (_firstPrev != dummyId) {
data.nodes[_firstPrev].nextId = _lastNext;
} else {
data.head = _lastNext;
}
if (_lastNext != dummyId) {
data.nodes[_lastNext].prevId = _firstPrev;
} else {
data.tail = _firstPrev;
}
// delete node & owner storages to get gas refund
for (uint i = 0; i < _len; ++i) {
delete data.nodes[_ids[i]];
emit NodeRemoved(_ids[i]);
}
size = size - _len;
}Function batchRemove(bytes32[] memory _ids) is used by CDP Manager to remove CDP IDs in batch. However, its assuming that _ids provided to remove are sorted in the same order as in the input array. If required ordering is not followed, it will also remove CDP's of the users which its not supposed to remove i.e., whose ID is not specified in _ids.
If this happened, it will remove CDP of some users, which then wont be able to claim their reward / collateral as their position is removed.
Impact
Since there is no validation on _ids to be in sorted order in the same way as in the input array, if its provided in out of order, it will remove some additional CDP's that its not intending to delete. Which will make those additional CDP position non existent from the system and the user belonging to those positions wont be able to claim their rewards / collateral back.
Recommendation
There should be a validation on _ids to be in a sorted order in the same way as in the input array. It can be done as below
References
https://github.com/ebtc-protocol/ebtc/blob/release-0.7/packages/contracts/contracts/SortedCdps.sol
Proof Of Concept
Steps to Run using Foundry:
Paste following foundry code in
/ebtc-boost/packages/contracts/foundry_test/SortedCdps.t.solRun using
forge test --match-contract CDPOpsTest --match-test testBatchRemoveInOrderRemovesMore -vvvv
Last updated
Was this helpful?