Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: low
Invalid

`updateVaultSwapStrategy` Allows Writing to Uninitialized Vault Storage Slots

Summary

The Vault::updateVaultSwapStrategy function uses load(vaultId) without verifying vault existence, allowing swap strategy settings to be written to uninitialized storage slots. While this doesn't affect existing vaults, it creates "ghost" settings that persist if a vault is later created at that slot.

Vulnerability Details

https://github.com/Cyfrin/2025-01-zaros-part-2/blob/35deb3e92b2a32cd304bf61d27e6071ef36e446d/src/market-making/leaves/Vault.sol#L488C4-L503C6

The function writes directly to storage slots without verifying if the vault exists (i.e., has been properly initialized with non-zero id).

POC:
Inside of VaultHarness.sol add the following selector to vaultHarnessSelectors -
vaultHarnessSelectors[18] = VaultHarness.workaround_getVaultSwapStrategyIds.selector;

The function we are adding -

function workaround_getVaultSwapStrategyIds(uint128 vaultId) external view returns (uint128, uint128) {
Vault.Data storage vaultData = Vault.load(vaultId);
return (
vaultData.swapStrategy.assetDexSwapStrategyId,
vaultData.swapStrategy.usdcDexSwapStrategyId
);
}

Paste this Test in rebalanceVaultsAssets.t.sol

function test_UpdateNonExistentVault(
uint256 adapterIndex
)
external
{
changePrank({ msgSender: users.owner.account });
//IDexAdapter adapter = getFuzzDexAdapter(adapterIndex);
marketMakingEngine.updateVaultSwapStrategy(
50, "", "", 3, 3
);
(uint128 assetId, uint128 usdcId) = marketMakingEngine.workaround_getVaultSwapStrategyIds(50);
assertEq(assetId, 3);
assertEq(usdcId, 3);
}

Impact

Can write swap strategy settings to uninitialized storage slots and the settings will persist even on newly created vaults with that ID until you call Vault::updateVaultSwapStrategy.

Tools Used

Foundry

Recommendations

Replace load() with loadExisting() to enforce vault existence check:

function updateVaultSwapStrategy(uint128 vaultId, ...) internal {
- Data storage self = load(vaultId);
+ Data storage self = loadExisting(vaultId); // Will revert if vault doesn't exist
self.swapStrategy = ...;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
6 months ago
inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

[INVALID]`updateVaultSwapStrategy` Allows Writing to Uninitialized Vault Storage Slots

Support

FAQs

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