owned this note
owned this note
Published
Linked with GitHub
# Yearn GUSD Vaults Write-up
## Problem #1: yGUSD share price is broken and vault is drained
Transaction in question, on [bloxy](https://bloxy.info/tx/0x307f83320e88d369d41799cbb64d05b36edd14ee927a3ffb7927e64f656d596a#). I also used tenderly to trace it, which was very helpful as well.
**Cause:** `earn` and `withdrawAll` calls on the [yvCurve-GUSD Vault](https://etherscan.io/address/0xcc7e70a958917cce67b4b87a8c30e6297451ae98#readContract) affect share price on the [yGUSD Vault](https://etherscan.io/token/0xec0d8d3ed5477106c6d4ea27d90a60e594693c90). This occurs because:
- `getPricePerFullShare` on yGUSD calls `balance`
- `balance` calls `balanceOf` from the [Controller](https://etherscan.io/address/0x9e65ad11b299ca0abefc2799ddb6314ef2d91080#code)
- The controller's `balanceOf` calls `balanceOf` from the [StrategyCurveGUSDProxy](https://etherscan.io/address/0xc8327d8e1094a94466e05a2cc1f10fa70a1df119) (this Vault's strategy)
- The strategy's `balanceOf` calls and adds `balanceOfPoolInWant` and `balanceOfWant`.
- `balanceOfPoolInWant` calls `balanceOfPool`
- The strategy's `balanceOfPool` calls `balanceOf` in the [StrategyProxy](https://etherscan.io/address/0xc17adf949f524213a540609c386035d7d685b16f#readContract) contract
- The StrategyProxy's `balanceOf` calls the gauge balance for Yearn's veCRV voter address ([CurveYCRVVoter](https://etherscan.io/address/0xf147b8125d2ef93fb6965db97d6746952a133934#code)). Yearn stakes LP tokens for Curve pools in the [GUSD gauge](https://etherscan.io/address/0xc5cfada84e902ad92dd40194f0883ad49639b023#readContract) to earn CRV emissions.
Both the yGUSD and yvCurve-GUSD Vaults ultimately deposit their LP tokens in the same gauge from the same address, so yGUSD saw the LP tokens yvCurve-GUSD deposited and thought those were its own, rapidly increasing the share price because no new yGUSD tokens were minted.
Currently, there are 7,371.81 outstanding yGUSD shares and only 1,357.33 GUSD in the vault. The current share price is ~37.76.
**Proposed Solution:** If we can just shut everything down completely, and send users the funds directly, that is easiest. Here's the [list]((https://docs.google.com/spreadsheets/d/1nNReLgKgAxJXq3QZ0LLEtokQipBB8_Ophig5_NSOkWk/edit?usp=sharing)) of holders of yGUSD. **Edit Jan 6th—share price is back to 0, all funds removed from v2 strat.**
If that's not possible, then I would suggest we deploy a new strategy with a hard-coded values for `balanceOf`. Simply put, we are breaking the connection between yGUSD and the GUSD Curve gauge.
Hard-code the `balanceOf` value to 1.77, and seed the vault with the appropriate amount of GUSD from treasury. Based on users with [outstanding shares](https://docs.google.com/spreadsheets/d/1nNReLgKgAxJXq3QZ0LLEtokQipBB8_Ophig5_NSOkWk/edit?usp=sharing), only two users deposited with average share prices above 1.77 (almost all were at 1.76xx). For one user, 0xddb7ffb26e58c9c71673f1f3965293dcfc860586, they already received more than their share, as they originally withdrew all shares (and [drained the vault](https://etherscan.io/token/0xec0d8d3ed5477106c6d4ea27d90a60e594693c90?a=0xddb7ffb26e58c9c71673f1f3965293dcfc860586)), getting ~7x their investment, then only to re-deposit 2,000 GUSD later (I can only imagine hoping to get a similar bonus? Maybe as a "thank you"?).
The only other user is 0x7b004ea66389ca8263632719fc2ded63af288912, who deposited once at a share price of ~1.76, but then deposited again a few days ago, leaving their average share price at 2.85. In the ethos of vaults never leaving users with less than they deposited, I propose we send them an extra 50 GUSD, since they will be able to redeem 77 at a share price of 1.77.
## Problem #2: yvCurve-GUSD share price is below 1
**Cause:** Whenever the last user drained the old GUSD vault [here](https://etherscan.io/tx/0x307f83320e88d369d41799cbb64d05b36edd14ee927a3ffb7927e64f656d596a), their `withdrawAll` transaction also removed 0.00000000000158595 GUSD/3Crv from the Curve gauge—this is the difference between the `balance` and `totalSupply` values for the new GUSD/3Crv vault. `getPricePerFullShare` is equal to `balance / totalSupply`, so this explains why the value is below 1.
This occurred because when a user withdraws, the vault checks to see if there are enough free funds to withdraw directly from the vault, or if it needs to pull from the strategy (in this cause withdrawing from the GUSD Curve gauge). Since the `balance` value was incorrectly skewed by the yvCurve-GUSD vault, this led to the following:
- [yGUSD Vault](https://etherscan.io/token/0xec0d8d3ed5477106c6d4ea27d90a60e594693c90) calculates `r = shares * balance / totalSupply = 2422549`
- Compares against `b = token.balanceOf(address(this)) = 836599` <- this is the GUSD sitting free in the vault
- In this case, `b < r`, which told the vault to pull funds from the strategy, equal to `r - b = 1585950`, so the strategy pulled 0.00000000000158595 gusd3CRV from the gauge and burned it.
In conclusion, we appeared to get **super fucking lucky** that there was both a bug in calculating `balance` **and** an issue with decimals—if the decimals weren't bugged as well, then this transaction would've withdrawn and burned (or maybe given the user?) 15,859.50 gusd3CRV.
Why did this burn happen though? Appears to be something that has been around since the vault launched, and was the same issue that broke it in the first place [here](https://etherscan.io/tx/0x645186de671252408401fb2255606d5d0803ef62a40b0c6e4112dcb1adc6c00c). My best guess is that the amount that's burned is too small to generate and tokens in return from Curve, but idk about that.
## Problem #3: yGUSD Vault and Strategy balances are incorrect on yearn.finance/stats
This should be fixed once the yGUSD vault and strategy are no longer pointing to the GUSD gauge.
## Problem #4: Setting GUSD strategy to zero address broke registry
Batch functions like `getVaultsInfo` in the vault registry (`registry.ychad.eth`) have stopped working.
**Cause:** Registry calls `strategy.want()` which reverts since 0x0 has no code.