Skip to content

Commit

Permalink
Fix exit requests (#106)
Browse files Browse the repository at this point in the history
* Simplify max boost calc

* Fix exit queue event handlers
  • Loading branch information
tsudmi authored Jan 10, 2025
1 parent 6c735f8 commit 7e6dd40
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 82 deletions.
77 changes: 25 additions & 52 deletions src/entities/vault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,60 +396,32 @@ export function updateVaultMaxBoostApy(
const vaultApy = getVaultApy(vault, false)
const osTokenMintApy = getVaultOsTokenMintApy(osToken, osTokenConfig)

// calculate max boost apy for vault allocator
const allocatorDepositedAssets = wad

// allocator mints max osToken shares
const allocatorMintedOsTokenAssets = allocatorDepositedAssets.times(osTokenConfig.ltvPercent).div(wad)
const allocatorMintedOsTokenShares = convertAssetsToOsTokenShares(osToken, allocatorMintedOsTokenAssets)

// osTokenHolder deposits all osToken shares
const osTokenHolderOsTokenAssets = allocatorMintedOsTokenAssets
const osTokenHolderOsTokenShares = allocatorMintedOsTokenShares
// initial amounts for calculating earnings
const boostedOsTokenAssets = wad
const boostedOsTokenShares = convertAssetsToOsTokenShares(osToken, wad)

// calculate assets/shares boosted from the strategy
const totalLtv = vaultLeverageLtv.times(aaveLeverageLtv).div(wad)
const strategyMintedOsTokenShares = osTokenHolderOsTokenShares
const strategyMintedOsTokenShares = boostedOsTokenShares
.times(wad)
.div(wad.minus(totalLtv))
.minus(osTokenHolderOsTokenShares)
.minus(boostedOsTokenShares)
const strategyMintedOsTokenAssets = convertOsTokenSharesToAssets(osToken, strategyMintedOsTokenShares)
const strategyDepositedAssets = strategyMintedOsTokenAssets.times(wad).div(vaultLeverageLtv)

// calculate earned assets from staking
let allocatorEarnedAssets = getAnnualReward(allocatorDepositedAssets.plus(strategyDepositedAssets), vaultApy)
let osTokenHolderEarnedAssets = getAnnualReward(osTokenHolderOsTokenAssets, osTokenApy).plus(
getAnnualReward(strategyDepositedAssets, vaultApy),
)
// calculate strategy earned assets from staking
let strategyEarnedAssets = getAnnualReward(strategyDepositedAssets, vaultApy)

// subtract apy lost on minting osToken
allocatorEarnedAssets = allocatorEarnedAssets.minus(
getAnnualReward(allocatorMintedOsTokenAssets.plus(strategyMintedOsTokenAssets), osTokenMintApy),
)
osTokenHolderEarnedAssets = osTokenHolderEarnedAssets.minus(
getAnnualReward(strategyMintedOsTokenAssets, osTokenMintApy),
)
strategyEarnedAssets = strategyEarnedAssets.minus(getAnnualReward(strategyMintedOsTokenAssets, osTokenMintApy))

// all supplied osToken shares earn supply apy
const allocatorEarnedOsTokenShares = getAnnualReward(
allocatorMintedOsTokenShares.plus(strategyMintedOsTokenShares),
supplyApy,
)
allocatorEarnedAssets = allocatorEarnedAssets.plus(
convertOsTokenSharesToAssets(osToken, allocatorEarnedOsTokenShares),
)
const osTokenHolderEarnedOsTokenShares = getAnnualReward(
osTokenHolderOsTokenShares.plus(strategyMintedOsTokenShares),
supplyApy,
)
osTokenHolderEarnedAssets = osTokenHolderEarnedAssets.plus(
convertOsTokenSharesToAssets(osToken, osTokenHolderEarnedOsTokenShares),
)
const earnedOsTokenShares = getAnnualReward(boostedOsTokenShares.plus(strategyMintedOsTokenShares), supplyApy)
strategyEarnedAssets = strategyEarnedAssets.plus(convertOsTokenSharesToAssets(osToken, earnedOsTokenShares))

// all borrowed assets lose borrow apy
const borrowInterestAssets = getAnnualReward(strategyDepositedAssets, borrowApy)
allocatorEarnedAssets = allocatorEarnedAssets.minus(borrowInterestAssets)
osTokenHolderEarnedAssets = osTokenHolderEarnedAssets.minus(borrowInterestAssets)
strategyEarnedAssets = strategyEarnedAssets.minus(borrowInterestAssets)

// all the supplied OsToken assets earn the additional incentives
const activeDistributionIds = distributor.activeDistributionIds
Expand All @@ -467,26 +439,27 @@ export function updateVaultMaxBoostApy(
continue
}

allocatorEarnedAssets = allocatorEarnedAssets.plus(
getAnnualReward(allocatorMintedOsTokenAssets.plus(strategyMintedOsTokenAssets), distributionApy),
)
osTokenHolderEarnedAssets = osTokenHolderEarnedAssets.plus(
getAnnualReward(osTokenHolderOsTokenAssets.plus(strategyMintedOsTokenAssets), distributionApy),
strategyEarnedAssets = strategyEarnedAssets.plus(
getAnnualReward(boostedOsTokenAssets.plus(strategyMintedOsTokenAssets), distributionApy),
)
}

// calculate average allocator max boost APY
const allocatorMaxBoostApy = new BigDecimal(allocatorEarnedAssets)
const allocatorDepositedAssets = boostedOsTokenAssets.times(wad).div(osTokenConfig.ltvPercent)
const allocatorEarnedAssets = strategyEarnedAssets
.plus(getAnnualReward(allocatorDepositedAssets, vaultApy))
.minus(getAnnualReward(boostedOsTokenAssets, osTokenMintApy))
vault.allocatorMaxBoostApy = allocatorEarnedAssets
.toBigDecimal()
.times(BigDecimal.fromString('100'))
.div(new BigDecimal(allocatorDepositedAssets))
.div(allocatorDepositedAssets.toBigDecimal())

// calculate average osToken holder APY
const osTokenHolderMaxBoostApy = new BigDecimal(osTokenHolderEarnedAssets)
// calculate average osToken holder max boost APY
const osTokenHolderEarnedAssets = strategyEarnedAssets.plus(getAnnualReward(boostedOsTokenAssets, osTokenApy))
vault.osTokenHolderMaxBoostApy = osTokenHolderEarnedAssets
.toBigDecimal()
.times(BigDecimal.fromString('100'))
.div(new BigDecimal(osTokenHolderOsTokenAssets))

vault.allocatorMaxBoostApy = allocatorMaxBoostApy
vault.osTokenHolderMaxBoostApy = osTokenHolderMaxBoostApy
.div(boostedOsTokenAssets.toBigDecimal())
vault.save()
}

Expand Down
71 changes: 41 additions & 30 deletions src/mappings/vault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,22 +315,6 @@ export function handleV1ExitQueueEntered(event: V1ExitQueueEntered): void {
const assets = convertSharesToAssets(vault, shares)
const timestamp = event.block.timestamp

// if it's ERC-20 vault shares are updated in Transfer event handler
if (!vault.isErc20) {
const osToken = loadOsToken()!
const osTokenConfig = loadOsTokenConfig(vault.osTokenConfig)!
const distributor = loadDistributor()!
const allocator = loadAllocator(owner, event.address)!
allocator.shares = allocator.shares.minus(shares)
updateAllocatorAssets(osToken, osTokenConfig, vault, allocator)
allocator.apy = getAllocatorApy(osToken, osTokenConfig, vault, distributor, allocator)
allocator.save()

if (allocator.shares.isZero()) {
decreaseUserVaultsCount(allocator.address)
}
}

createAllocatorAction(event, event.address, AllocatorActionType.ExitQueueEntered, owner, assets, shares)

createTransaction(event.transaction.hash.toHex())
Expand All @@ -357,6 +341,24 @@ export function handleV1ExitQueueEntered(event: V1ExitQueueEntered): void {
exitRequest.isClaimed = false
exitRequest.save()

const osToken = loadOsToken()!
const osTokenConfig = loadOsTokenConfig(vault.osTokenConfig)!
const distributor = loadDistributor()!
const allocator = loadAllocator(owner, event.address)!

// if it's ERC-20 vault shares are updated in Transfer event handler
if (!vault.isErc20) {
allocator.shares = allocator.shares.minus(shares)
updateAllocatorAssets(osToken, osTokenConfig, vault, allocator)

if (allocator.shares.isZero()) {
decreaseUserVaultsCount(allocator.address)
}
}

allocator.apy = getAllocatorApy(osToken, osTokenConfig, vault, distributor, allocator)
allocator.save()

log.info('[Vault] V1ExitQueueEntered vault={} owner={} shares={}', [
vaultAddressHex,
owner.toHex(),
Expand Down Expand Up @@ -396,20 +398,6 @@ export function handleV2ExitQueueEntered(event: V2ExitQueueEntered): void {
network.totalAssets = network.totalAssets.minus(assets)
network.save()

// Update allocator shares
const osToken = loadOsToken()!
const osTokenConfig = loadOsTokenConfig(vault.osTokenConfig)!
const distributor = loadDistributor()!
const allocator = loadAllocator(owner, vaultAddress)!
allocator.shares = allocator.shares.minus(shares)
updateAllocatorAssets(osToken, osTokenConfig, vault, allocator)
allocator.apy = getAllocatorApy(osToken, osTokenConfig, vault, distributor, allocator)
allocator.save()

if (allocator.shares.isZero()) {
decreaseUserVaultsCount(allocator.address)
}

createAllocatorAction(event, vaultAddress, AllocatorActionType.ExitQueueEntered, owner, assets, shares)

createTransaction(event.transaction.hash.toHex())
Expand All @@ -433,6 +421,20 @@ export function handleV2ExitQueueEntered(event: V2ExitQueueEntered): void {
exitRequest.isClaimed = false
exitRequest.save()

// Update allocator shares
const osToken = loadOsToken()!
const osTokenConfig = loadOsTokenConfig(vault.osTokenConfig)!
const distributor = loadDistributor()!
const allocator = loadAllocator(owner, vaultAddress)!
allocator.shares = allocator.shares.minus(shares)
updateAllocatorAssets(osToken, osTokenConfig, vault, allocator)
allocator.apy = getAllocatorApy(osToken, osTokenConfig, vault, distributor, allocator)
allocator.save()

if (allocator.shares.isZero()) {
decreaseUserVaultsCount(allocator.address)
}

log.info('[Vault] V2ExitQueueEntered vault={} owner={} shares={} assets={}', [
vaultAddressHex,
owner.toHex(),
Expand Down Expand Up @@ -498,6 +500,15 @@ export function handleExitedAssetsClaimed(event: ExitedAssetsClaimed): void {
prevExitRequest.isClaimed = true
prevExitRequest.save()

// update allocator APY
const vault = loadVault(vaultAddress)!
const osToken = loadOsToken()!
const osTokenConfig = loadOsTokenConfig(vault.osTokenConfig)!
const distributor = loadDistributor()!
const allocator = loadAllocator(prevExitRequest.owner, vaultAddress)!
allocator.apy = getAllocatorApy(osToken, osTokenConfig, vault, distributor, allocator)
allocator.save()

log.info('[Vault] ExitedAssetsClaimed vault={} prevPositionTicket={} newPositionTicket={} claimedAssets={}', [
vaultAddressHex,
prevPositionTicket.toString(),
Expand Down

0 comments on commit 7e6dd40

Please sign in to comment.