Open hats-bug-reporter[bot] opened 10 months ago
While weights aren't emitted on vault creation (because not all vaults might have weights). As such, we can't emit the values on creation. Instead they have to be read. We are aware of the danger of weights, see this report from Veridise:
https://github.com/catalystdao/catalyst/blob/main/evm/audit/VAR_Catalyst-v1.pdf, page 19.
When users deposit into vaults, it must be assumed that they know exactly what the profile of the vault is (or was relativly close to before they created their transaction). Thus the weights are assumed to be part of that.
You should also be aware that the weights directly impact the cost of the vaults AND at high weights the vault might even begin to malfunction. Generally we advise users to keep the weights low-ish. (Around 10**6) but they can be set even lower to "opt-out" of governance weight changes. https://github.com/hats-finance/Catalyst-Exchange-0x3026c1ea29bf1280f99b41934b2cb65d053c9db4/blob/fba322fab023a9206183fb455e9f86facd550d8a/evm/src/CatalystVaultVolatile.sol#L136-L142
Likewise, the governance is only able to adjust weight changes with a small-ish window: https://github.com/hats-finance/Catalyst-Exchange-0x3026c1ea29bf1280f99b41934b2cb65d053c9db4/blob/fba322fab023a9206183fb455e9f86facd550d8a/evm/src/CatalystVaultVolatile.sol#L165
To be specific the Veridise report deals with a setWeights()
, which can be only used and exploited by the factory owner and as you said has restrictions on weight changes. This is an entirely different issue which can be exploited by any vault deployer and has no restrictions, only relates to the report that both vulnerabilities uses weights
.
When users deposit into vaults, it must be assumed that they know exactly what the profile of the vault is (or was relativly close to before they created their transaction). Thus the weights are assumed to be part of that.
I understand, but it's dangerous to delegate this responsibility fully to users. Realistically not every user (if not the majority of users) is going to fully validate the vault, or in this particular case the weights
of the vault. I think it's too risky to let this as is, as the likelihood of a potentially exploit is high, because it's very easy to setup as a vault deployer and the impact is total loss of funds for LPs.
That is why these things are done via a UI rather than directly on the contract.
Realistically, how many are going to setup the vaults correctly if they don't have access to a UI? How many are going to deposit straight to the vault without the UI?
Github username: @0xfuje Twitter username: 0xfuje Submission hash (on-chain): 0x5080e114a5766d73acf6fcc4a43ef0d8f1efff65669819a66efef50f41d4aff3 Severity: high
Description:
Impact
Total loss of LP deposited funds of the vulnerable Vault
Description
The root of the problem is the unbounded nature of token
weights
ofCatalystVaults
, which can be set to any value without restriction. A disproportionately large weight difference can be used to drain the vault.Vault
from the whitelisted templates withUSDC
,USDT
andWETH
with a normal distribution ($1000 USDC + $1000 USDT + 1 WETH), but sets the weight ofWETH
absurdly highUSDC
, $10000USDT
and 10 WETHWETH
toUSDC
&USDT
immediately draining the LP's funds from theVault
and profiting $20000 from the LP'sUSDC
&USDT
fundsProof of Concept
test/ExampleTest.t.sol
Copy and switch the initial setup for the below setup
call
forge test --match-test --via-ir test_localswap_exploit_unbalance -vvvv
Recommendation
Consider to bound token weight to be between a reasonable value (taking into account the token decimals), as this would minimize potential damage (e.g. can't exceed 100x or 10x difference). Consider to add
weights
as an event param toVaultDeployed()
. This issue seems hard to completely mitigate, some kind of additional restriction could be used onlocalSwap()
and LP functions to prevent highly unfavorable conversations due to weight differences.