Summary
A critical vulnerability exists in the createVault
function due to the lack of uniqueness checks for vaultId
. This flaw allows an attacker or an accidental misconfiguration to overwrite existing vault configurations, potentially leading to loss of data, disruption of system operations, and financial loss.
Vulnerability Details
The createVault
function does not verify whether the provided vaultId
has already been used. This means that if a duplicate vaultId
is provided, it will overwrite an existing vault configuration without warning.
function createVault(Vault.CreateParams calldata params) external onlyOwner {
if (params.indexToken == address(0)) {
revert Errors.ZeroInput("indexToken");
}
if (params.depositCap == 0) {
revert Errors.ZeroInput("depositCap");
}
if (params.withdrawalDelay == 0) {
revert Errors.ZeroInput("withdrawDelay");
}
if (params.vaultId == 0) {
revert Errors.ZeroInput("vaultId");
}
if (params.engine == address(0)) {
revert Errors.ZeroInput("engine");
}
Vault.create(params);
emit LogCreateVault(msg.sender, params.vaultId);
}
PoC
A malicious or unintended transaction creates a vault with an existing vaultId
, overwriting its configuration.
contract VaultCollisionTest is Test {
VaultContract vaultContract;
address owner = address(0x123);
function setUp() public {
vaultContract = new VaultContract();
vm.startPrank(owner);
}
function test_VaultCollision() public {
Vault.CreateParams memory params1 = Vault.CreateParams({
vaultId: 1,
depositCap: 1000,
withdrawalDelay: 3600,
indexToken: address(0xABC),
collateral: Collateral.Data({ asset: address(0xDEF), priceAdapter: address(0x123), creditRatio: 50, isEnabled: true, decimals: 18 }),
depositFee: 10,
redeemFee: 5,
engine: address(0x456)
});
vaultContract.createVault(params1);
Vault.CreateParams memory params2 = params1;
params2.depositCap = 5000;
vaultContract.createVault(params2);
uint256 newDepositCap = vaultContract.getVaultDepositCap(1);
assertEq(newDepositCap, 5000, "Vault ID collision detected: depositCap changed unexpectedly!");
}
}
Output:
[FAIL] test_VaultCollision() : Vault ID collision detected: depositCap changed unexpectedly!
Impact
Vault configurations can be accidentally or maliciously overwritten.
Previously deployed vaults may stop working as expected.
If vault parameters like deposit caps or withdrawal delays are altered, users might lose funds or be unable to access the
Tools Used
Manual review.
Recommendations
Before creating a vault, verify that the ID does not already exist.
Implement a check that prevents overwriting an existing vault.
function createVault(Vault.CreateParams calldata params) external onlyOwner {
require(!vaultExists(params.vaultId), "Vault ID already exists");
Vault.create(params);
emit LogCreateVault(msg.sender, params.vaultId);
}
function vaultExists(uint256 vaultId) internal view returns (bool) {
return vaultsConfig[vaultId].vaultId != 0;
}