Skip to content

Commit

Permalink
Fix rebalance
Browse files Browse the repository at this point in the history
  • Loading branch information
shanejearley committed May 31, 2023
1 parent 7bceb2f commit 642cd23
Show file tree
Hide file tree
Showing 12 changed files with 742 additions and 612 deletions.
510 changes: 273 additions & 237 deletions contracts/ethereum/docs/index.md

Large diffs are not rendered by default.

100 changes: 32 additions & 68 deletions contracts/ethereum/helpers/upkeep.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,40 @@
import { ethers } from 'hardhat'
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'
import { CasimirManager, CasimirUpkeep } from '../build/artifacts/types'
import { CasimirUpkeep } from '../build/artifacts/types'

export enum RequestType {
BALANCE = 0,
DEPOSITS = 1,
EXITS = 2,
SLASHES = 3
export interface ReportValues {
activeBalance: number
activatedDeposits: number
unexpectedExits: number
slashedExits: number
withdrawnExits: number
}

export async function performReport({
manager,
export async function fulfillReportRequest({
upkeep,
keeper,
values,
requestId
requestId,
values
}: {
manager: CasimirManager,
upkeep: CasimirUpkeep,
keeper: SignerWithAddress,
values: number[],
requestId: number
}) {
await runUpkeep({ upkeep, keeper })

for (let i = 0; i < values.length; i++) {
const value = values[i]
const checkBalance = i == RequestType.BALANCE
const checkDeposits = i == RequestType.DEPOSITS && (await manager.getPendingPoolIds()).length > 0
const checkExits = i == RequestType.EXITS && (await manager.getExitingPoolCount()).toNumber() > 0
const checkSlashes = i == RequestType.SLASHES
if (checkBalance || checkDeposits || checkExits || checkSlashes) {
requestId++
await fulfillFunctionsRequest({
upkeep,
keeper,
value: checkBalance ? ethers.utils.parseEther(value.toString()).toString() : value.toString(),
requestId
})
}
}

await runUpkeep({ upkeep, keeper })

requestId: number,
values: ReportValues
}) {
requestId++
const requestIdHash = ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['uint256'], [requestId]))
const { activeBalance, activatedDeposits, unexpectedExits, slashedExits, withdrawnExits } = values
const activeBalanceGwei = ethers.utils.parseUnits(activeBalance.toString(), 'gwei')
const responseBytes = ethers.utils.defaultAbiCoder.encode(
['uint128', 'uint32', 'uint32', 'uint32', 'uint32'],
[activeBalanceGwei, activatedDeposits, unexpectedExits, slashedExits, withdrawnExits]
)
await fulfillFunctionsRequest({
upkeep,
keeper,
requestIdHash,
responseBytes
})
return requestId
}

Expand All @@ -67,42 +59,14 @@ export async function runUpkeep({
export async function fulfillFunctionsRequest({
upkeep,
keeper,
value,
requestId
requestIdHash,
responseBytes
}: {
upkeep: CasimirUpkeep,
keeper: SignerWithAddress,
value: string,
requestId: number
requestIdHash: string,
responseBytes: string
}) {
const requestIdHash = ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['uint256'], [requestId]))
const response = ethers.BigNumber.from(value)
const responseBytes = ethers.utils.defaultAbiCoder.encode(['uint256'], [response.toString()])
const errorBytes = ethers.utils.toUtf8Bytes('')
const mockFulfillRequest = await upkeep.connect(keeper).mockFulfillRequest(requestIdHash, responseBytes, errorBytes)
const mockFulfillRequest = await upkeep.connect(keeper).mockFulfillRequest(requestIdHash, responseBytes, [])
await mockFulfillRequest.wait()
}

export function packResponse({ values, bits }: { values: string[], bits: number[] }) {
let packed = ethers.BigNumber.from('0')
values.forEach((value, i) => {
if (i === 0) {
console.log('active value', value)
packed = ethers.BigNumber.from(value)
} else {
const shift = bits.slice(0, i).reduce((a, b) => a + b, 0)
packed = packed.or(ethers.BigNumber.from(value).shl(shift))
}
})
return packed
}

export function unpackResponse({ packed, bits }: { packed: string, bits: number[] }) {
return bits.map((_, i) => {
if (i === 0) {
return ethers.BigNumber.from(packed).and(ethers.BigNumber.from('0xFFFFFFFFFFFFFFFF')).toString()
}
const shift = bits.slice(0, i).reduce((a, b) => a + b, 0)
return ethers.BigNumber.from(packed).shr(shift).and(ethers.BigNumber.from('0xFFFFFFFFFFFFFFFF')).toString()
})
}
52 changes: 32 additions & 20 deletions contracts/ethereum/scripts/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { deployContract } from '@casimir/ethereum/helpers/deploy'
import { ContractConfig, DeploymentConfig } from '@casimir/types'
import { CasimirUpkeep, CasimirManager } from '@casimir/ethereum/build/artifacts/types'
import { ethers } from 'hardhat'
import { performReport } from '@casimir/ethereum/helpers/upkeep'
import { fulfillReportRequest, runUpkeep } from '@casimir/ethereum/helpers/upkeep'
import { round } from '@casimir/ethereum/helpers/math'
import EventEmitter, { on } from 'events'
import { time, setBalance } from '@nomicfoundation/hardhat-network-helpers'
Expand Down Expand Up @@ -85,6 +85,9 @@ void async function () {
if (depositedPoolCount) {
console.log(`Rewarding ${depositedPoolCount} validators ${rewardPerValidator} each`)
await time.increase(time.duration.days(1))

await runUpkeep({ upkeep, keeper })

const rewardAmount = rewardPerValidator * depositedPoolCount.toNumber()
let nextActiveBalance = round(
parseFloat(
Expand All @@ -93,48 +96,57 @@ void async function () {
)
) + rewardAmount
)
let nextDeposits = (await manager.getPendingPoolIds()).length
let nextValues = [
nextActiveBalance, // activeBalance
nextDeposits, // deposits
0, // exits
0, // slashes
]
requestId = await performReport({
manager,

let nextActivatedDeposits = (await manager.getPendingPoolIds()).length
let nextValues = {
activeBalance: nextActiveBalance,
activatedDeposits: nextActivatedDeposits,
unexpectedExits: 0,
slashedExits: 0,
withdrawnExits: 0
}

requestId = await fulfillReportRequest({
upkeep,
keeper,
values: nextValues,
requestId
})

/** Sweep rewards before next upkeep (balance will increment silently) */
await runUpkeep({ upkeep, keeper })

const currentBalance = await ethers.provider.getBalance(manager.address)
const nextBalance = currentBalance.add(ethers.utils.parseEther(rewardAmount.toString()))
await setBalance(manager.address, nextBalance)

await time.increase(time.duration.days(1))

await runUpkeep({ upkeep, keeper })

nextActiveBalance = round(
parseFloat(
ethers.utils.formatEther(
(await manager.getLatestActiveBalance()).add((await manager.getPendingPoolIds()).length * 32)
)
) - rewardAmount
)
nextDeposits = (await manager.getPendingPoolIds()).length
nextValues = [
nextActiveBalance, // activeBalance
nextDeposits, // deposits
0, // exits
0, // slashes
]
requestId = await performReport({
manager,
nextActivatedDeposits = (await manager.getPendingPoolIds()).length
nextValues = {
activeBalance: nextActiveBalance,
activatedDeposits: nextActivatedDeposits,
unexpectedExits: 0,
slashedExits: 0,
withdrawnExits: 0
}

requestId = await fulfillReportRequest({
upkeep,
keeper,
values: nextValues,
requestId
})

await runUpkeep({ upkeep, keeper })
}
}
}
Expand Down
Loading

0 comments on commit 642cd23

Please sign in to comment.