Skip to content

v3.0.3 Report on self with refund accounting bug

Low
Schlagonia published GHSA-fjpv-hq67-rcgh Oct 18, 2024

Package

No package listed

Affected versions

v3.0.3

Patched versions

None

Description

In cases when calling process_report(self) on a vault with both a gain and a non-zero total_refund the vault total_idle balance will be updated incorrectly.

In _process_report, in the case there is an accountant that returns some non-zero total_refunds, shares are minted (or not burned if there were shares to be burned) for that refund and are supposed to be locked.

# Get the amount we will lock to avoid a PPS increase.
if gain + total_refunds > 0 and profit_max_unlock_time != 0:
  shares_to_lock = self._convert_to_shares(gain + total_refunds, Rounding.ROUND_DOWN)

Later, the refunds are pulled from the accountant and total_idle is updated given that we are minting new shares so they have to be backed by assets in total_idle to keep the pps constant (as the share are to be locked):

# Pull refunds

if total_refunds > 0:
  # Transfer the refunded amount of asset to the vault.
  self._erc20_safe_transfer_from(_asset, accountant, self, total_refunds)
  # Update storage to increase total assets.
  self.total_idle += total_refunds

However, if there were gain, total_idle is overwritten with total_assets which is the balance of the contract before pulling the refunds

# Record any reported gains.

if gain > 0:
  # NOTE: this will increase total_assets
  current_debt = unsafe_add(current_debt, gain)
  if strategy != self:
    self.strategies[strategy].current_debt = current_debt
    self.total_debt += gain
  else:
    self.total_idle = total_assets

In this scenario total_idle will not reflect the addition of the refunds, and the shares to lock will still be minted.

Note that a similar behaviour is present in the branch elif loss > 0.

Thanks to the ChainSec team for raising this issue.

Impact

  • This bug was introduced in v3.0.3 and isolated to multi strategy vaults on that version only.
  • The code path is only accessible on multi strategy vaults, and when the following conditions are true:
    • an accountant is set
    • the accountant issues a refund > 0
    • the vault's asset balance does not match total_idle
    • a call to process_report(self) is made

Patches

v3.0.4 will provide needed patches

Workarounds

  • Do not issue refunds when reporting on self to accrue any airdropped total_idle
  • Calling process_report(self) again with no refunds will cause the accounting to correct itself. Note: the corrective amounts may be locked and or have fees taken out depending on the vaults and vault accountants configuration.

Severity

Low

CVE ID

No known CVE

Weaknesses

No CWEs

Credits