Skip to content

Commit

Permalink
Add collateral recovery
Browse files Browse the repository at this point in the history
  • Loading branch information
shanejearley committed Jun 5, 2023
1 parent 0ca0dd9 commit 30728d6
Show file tree
Hide file tree
Showing 30 changed files with 1,397 additions and 1,067 deletions.
6 changes: 3 additions & 3 deletions apps/web/src/composables/ssv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default function useSSV() {
console.log('poolIds :>> ', poolIds)

return await Promise.all(poolIds.map(async (poolId: number) => {
const { deposits, publicKey, operatorIds } = await manager.connect(provider).getPool(poolId)
const { publicKey, operatorIds } = await manager.connect(provider).getPoolDetails(poolId)

// TODO: Decide when/how to get rewards/userRewards
let pool: Pool = {
Expand All @@ -98,12 +98,12 @@ export default function useSSV() {


// TODO: Replace with less hardcoded network call?
const operators = await Promise.all(operatorIds.map(async (operatorId: number) => {
const operators = await Promise.all(operatorIds.map(async (operatorId) => {
const network = 'prater'
const response = await fetch(`https://api.ssv.network/api/v3/${network}/operators/${operatorId}`)
const { performance } = await response.json()
return {
id: operatorId,
id: operatorId.toNumber(),
'24HourPerformance': performance['24h'],
'30DayPerformance': performance['30d'],
url: `https://explorer.ssv.network/operators/${operatorId}`
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/composables/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ export default function useUsers () {
address: manager.address,
topics: [
// ethers.utils.id('ManagerDistribution(address,uint256,uint256,uint256)'), // TODO: Make sure to query for past events on page load (Fetch and then subscribe),
ethers.utils.id('PoolDepositInitiated(uint32)'),
ethers.utils.id('DepositInitiated(uint32)'),
]
}
manager.connect(provider).on(validatorInitFilter, async () => {
Expand Down
2 changes: 1 addition & 1 deletion common/ssv/src/interfaces/ClusterDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import { BigNumber } from 'ethers'

export interface ClusterDetails {
cluster: Cluster,
requiredFees: BigNumber
requiredBalancePerValidator: BigNumber
}
4 changes: 2 additions & 2 deletions common/ssv/src/interfaces/ClusterDetailsInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { ethers } from 'ethers'
export interface ClusterDetailsInput {
/** JSON RPC node provider */
provider: ethers.providers.JsonRpcProvider
/** Owner address */
ownerAddress: string
/** Operator IDs */
operatorIds: number[]
/** Withdrawal address */
withdrawalAddress: string
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ethers } from 'ethers'

export interface ExchangeRateInput {
export interface PriceInput {
/** JSON RPC node provider */
provider: ethers.providers.JsonRpcProvider
/** The input token */
Expand Down
41 changes: 23 additions & 18 deletions common/ssv/src/providers/clusters.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { ethers } from 'ethers'
import { SSVNetwork, SSVNetworkViews } from '@casimir/ethereum/build/artifacts/types'
import SSVNetworkJson from '@casimir/ethereum/build/artifacts/scripts/resources/ssv-network/contracts/SSVNetwork.sol/SSVNetwork.json'
import SSVNetworkJsonViews from '@casimir/ethereum/build/artifacts/scripts/resources/ssv-network/contracts/SSVNetworkViews.sol/SSVNetworkViews.json'
import { ISSVNetwork, ISSVNetworkViews } from '@casimir/ethereum/build/artifacts/types'
import ISSVNetworkJson from '@casimir/ethereum/build/artifacts/scripts/resources/ssv-network/contracts/ISSVNetwork.sol/ISSVNetwork.json'
import ISSVNetworkViewsJson from '@casimir/ethereum/build/artifacts/scripts/resources/ssv-network/contracts/ISSVNetworkViews.sol/ISSVNetworkViews.json'
import { ClusterDetailsInput } from '../interfaces/ClusterDetailsInput'
import { ClusterDetails } from '../interfaces/ClusterDetails'
import { Cluster } from '@casimir/types'
import { getExchangeRate } from './uniswap'
import { getPrice } from './uniswap'

const networkAddress = '0xAfdb141Dd99b5a101065f40e3D7636262dce65b3'
const networkViewsAddress = '0x8dB45282d7C4559fd093C26f677B3837a5598914'
Expand All @@ -30,12 +30,12 @@ const eventList = [
* @returns {Promise<Cluster>} Cluster snapshot
*/
export async function getClusterDetails(input: ClusterDetailsInput): Promise<ClusterDetails> {
const { provider, operatorIds, withdrawalAddress } = input
const { provider, ownerAddress, operatorIds } = input

const ssvNetwork = new ethers.Contract(networkAddress, SSVNetworkJson.abi, provider) as SSVNetwork & ethers.Contract
const ssvNetworkViews = new ethers.Contract(networkViewsAddress, SSVNetworkJsonViews.abi, provider) as SSVNetworkViews & ethers.Contract
const ssvNetwork = new ethers.Contract(networkAddress, ISSVNetworkJson.abi, provider) as ISSVNetwork & ethers.Contract
const ssvNetworkViews = new ethers.Contract(networkViewsAddress, ISSVNetworkViewsJson.abi, provider) as ISSVNetworkViews & ethers.Contract

const eventFilters = eventList.map(event => ssvNetwork.filters[event](withdrawalAddress))
const eventFilters = eventList.map(event => ssvNetwork.filters[event](ownerAddress))

let step = MONTH
const latestBlockNumber = await provider.getBlockNumber()
Expand Down Expand Up @@ -97,17 +97,22 @@ export async function getClusterDetails(input: ClusterDetailsInput): Promise<Clu
active: true
}

const exchangeRate = await getExchangeRate({ provider, tokenIn: wethTokenAddress, tokenOut: networkTokenAddress, uniswapFeeTier: 3000 })
console.log('EXCHANGE RATE', exchangeRate)
const price = await getPrice({
provider,
tokenIn: wethTokenAddress,
tokenOut: networkTokenAddress,
uniswapFeeTier: 3000
})

let requiredFees
if (cluster.validatorCount) {
requiredFees = 0
// Can also top off cluster here
const feeSum = await ssvNetworkViews.getNetworkFee()
for (const operatorId of operatorIds) {
const operatorFee = await ssvNetworkViews.getOperatorFee(operatorId)
feeSum.add(operatorFee)
}
// Get a minimum runway for the next validator
const liquidationThresholdPeriod = await ssvNetworkViews.getLiquidationThresholdPeriod()
const ssvBalanceRequiredPerValidator = ethers.utils.formatEther(feeSum.mul(liquidationThresholdPeriod).mul(12))
const ethBalanceRequiredPerValidator = (Number(ssvBalanceRequiredPerValidator) * price).toPrecision(9)
const requiredBalancePerValidator = ethers.utils.parseEther(ethBalanceRequiredPerValidator)

requiredFees = ethers.utils.parseEther('0.1')

return { cluster, requiredFees }
return { cluster, requiredBalancePerValidator }
}
8 changes: 4 additions & 4 deletions common/ssv/src/providers/uniswap.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { ethers } from 'ethers'
import { ExchangeRateInput } from '../interfaces/ExchangeRateInput'
import { PriceInput } from '../interfaces/PriceInput'
import IUniswapV3FactoryJson from '@casimir/ethereum/build/artifacts/@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol/IUniswapV3Factory.json'
import IUniswapV3PoolStateJson from '@casimir/ethereum/build/artifacts/@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol/IUniswapV3PoolState.json'
import { IUniswapV3Factory, IUniswapV3PoolState } from '@casimir/ethereum/build/artifacts/types'

const uniswapV3FactoryAddress = '0x1F98431c8aD98523631AE4a59f267346ea31F984'

export async function getExchangeRate(input: ExchangeRateInput) {
export async function getPrice(input: PriceInput) {
const { provider, tokenIn, tokenOut, uniswapFeeTier } = input
const uniswapV3FactoryContract = new ethers.Contract(uniswapV3FactoryAddress, IUniswapV3FactoryJson.abi, provider) as IUniswapV3Factory & ethers.Contract
const poolAddress = await uniswapV3FactoryContract.getPool(tokenIn, tokenOut, uniswapFeeTier)
const poolContract = new ethers.Contract(poolAddress, IUniswapV3PoolStateJson.abi, provider) as IUniswapV3PoolState & ethers.Contract
const slot0 = await poolContract.slot0()
const tick = slot0.tick // price (tick) = 1.0001 ^ tick
return Math.pow(1.0001, tick)
const tick = slot0.tick
return 1.0001 ** tick
}
Loading

0 comments on commit 30728d6

Please sign in to comment.