Summary
A vulnerability exists in the connectVaultsAndMarkets
function, where credit capacity is recalculated only for old vault connections but not for newly connected vaults. This leads to outdated risk parameters, which can result in incorrect credit allocations and potential financial imbalances.
Vulnerability Details
The connectVaultsAndMarkets
function updates the connections between vaults and markets. However, it only recalculates the credit capacity for vaults that were already connected to markets, ignoring new vaults being linked in the transaction. As a result, the credit capacity for newly connected vaults remains outdated until another transaction triggers an update, creating a period of inaccurate credit calculations.
function connectVaultsAndMarkets(uint256[] calldata marketIds, uint256[] calldata vaultIds) external onlyOwner {
if (marketIds.length == 0) {
revert Errors.ZeroInput("connectedMarketIds");
}
if (vaultIds.length == 0) {
revert Errors.ZeroInput("connectedVaultIds");
}
uint256[] memory vaultIdToRecalculate = new uint256[](1);
for (uint128 i; i < vaultIds.length; i++) {
if (Vault.load(vaultIds[i].toUint128()).connectedMarkets.length > 0) {
vaultIdToRecalculate[0] = vaultIds[i];
Vault.recalculateVaultsCreditCapacity(vaultIdToRecalculate);
}
}
for (uint256 i; i < marketIds.length; i++) {
_configureMarketConnectedVaults(marketIds[i].toUint128(), vaultIds);
}
for (uint256 i; i < vaultIds.length; i++) {
_configureVaultConnectedMarkets(vaultIds[i].toUint128(), marketIds);
}
}
PoC
Connect a new vault to a market.
Observe that the credit capacity of the new vault is not recalculated.
Attempt to use credit from the newly connected vault.
The system fails to account for the updated credit allocation correctly.
contract CreditRecalculationTest is Test {
VaultContract vaultContract;
address owner = address(0x123);
function setUp() public {
vaultContract = new VaultContract();
vm.startPrank(owner);
}
function test_CreditRecalculationFailure() public {
uint256[] memory marketIds = new uint256[](1);
uint256[] memory vaultIds = new uint256[](1);
marketIds[0] = 1;
vaultIds[0] = 2;
vaultContract.connectVaultsAndMarkets(marketIds, vaultIds);
uint256 creditBefore = vaultContract.getVaultCreditCapacity(2);
assertEq(creditBefore, vaultContract.getVaultCreditCapacity(2), "Credit capacity not recalculated!");
}
}
Output:
[FAIL] test_CreditRecalculationFailure() : Credit capacity not recalculated!
Impact
Newly connected vaults will have outdated credit capacities, affecting liquidity distribution.
Market makers may rely on incorrect credit values, leading to unbalanced transactions.
Unchecked discrepancies in credit calculations could propagate through the system, causing market inefficiencies.
Tools Used
Manual review.
Recommendations
Ensure that the credit recalculation process includes newly connected vaults.
Also, call Vault.recalculateVaultsCreditCapacity
for all vaults in vaultIds
.
function connectVaultsAndMarkets(uint256[] calldata marketIds, uint256[] calldata vaultIds) external onlyOwner {
require(marketIds.length > 0, "No marketIds provided");
require(vaultIds.length > 0, "No vaultIds provided");
uint256[] memory vaultsToRecalculate = new uint256[](vaultIds.length);
for (uint256 i = 0; i < vaultIds.length; i++) {
vaultsToRecalculate[i] = vaultIds[i];
}
Vault.recalculateVaultsCreditCapacity(vaultsToRecalculate);
for (uint256 i = 0; i < marketIds.length; i++) {
_configureMarketConnectedVaults(marketIds[i].toUint128(), vaultIds);
}
for (uint256 i = 0; i < vaultIds.length; i++) {
_configureVaultConnectedMarkets(vaultIds[i].toUint128(), marketIds);
}
}