Skip to content

Commit

Permalink
add blockNumber and debug options
Browse files Browse the repository at this point in the history
  • Loading branch information
trmid committed Apr 10, 2024
1 parent af6c111 commit 3016ee7
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 22 deletions.
53 changes: 46 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,6 @@ Compile a list of potential winners that you want to check against, a given priz
}
```

> You can optionally define a `multicallBatchSize` argument in the input json file to limit multicall sizes for your RPC calls. Some RPC enforce "gas" limits on read calls and will only accept certain batch sizes:
```json
{
"multicallBatchSize": 50
}
```

### Step 2

Define your desired RPC URL as a local environment variable like so:
Expand Down Expand Up @@ -70,3 +63,49 @@ When the script finishes, the results will be written to your output file locati
]
}
```

## Optional Arguments

Optional arguments can be set in the input JSON file to change the behaviour of the script.

--------------------------------------------------------------------------------

### multicallBatchSize

Set the `multicallBatchSize` argument in the input json file to limit multicall sizes for your RPC calls. Some RPC enforce "gas" limits on read calls and will only accept certain batch sizes.

#### Example:

```json
{
"multicallBatchSize": 50
}
```

--------------------------------------------------------------------------------

### blockNumber

The `blockNumber` argument can be set to run the script at a specific block number instead of the current block. Must be either a number or string that can be parsed into a `BigInt`.

#### Example:

```json
{
"blockNumber": "10448512"
}
```

--------------------------------------------------------------------------------

### debug

The `debug` argument is an optional boolean. When set, some extra logs will be included in the output logs to help debug issues.

#### Example:

```json
{
"debug": true
}
```
8 changes: 6 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ const outputFile = process.argv[3]
const rpcUrl = process.env.FWC_RPC_URL

const run = async () => {
const { chainId, multicallBatchSize, prizePoolAddress, vaultAddress, userAddresses } = JSON.parse(fs.readFileSync(inputFile, 'utf8'))
const { chainId, multicallBatchSize, prizePoolAddress, vaultAddress, userAddresses, debug, blockNumber } = JSON.parse(fs.readFileSync(inputFile, 'utf8'))
const parsedBlockNumber = !!blockNumber ? BigInt(blockNumber) : undefined;

const paramBatches = await getAllParams(chainId, rpcUrl, prizePoolAddress, vaultAddress, userAddresses, { multicallBatchSize })
const paramBatches = await getAllParams(chainId, rpcUrl, prizePoolAddress, vaultAddress, userAddresses, { multicallBatchSize, blockNumber: parsedBlockNumber })

const scriptPath = join(rootDir, './sol/script/WinnerCalc.s.sol')
const configPath = join(rootDir, './sol/foundry.toml')
Expand All @@ -31,6 +32,9 @@ const run = async () => {
await new Promise((resolve, reject) => {
exec(`forge script ${scriptPath}:WinnerCalcScript --config-path ${configPath} --cache-path ${cachePath} --memory-limit 268435456 --skip-simulation`, (error, stdout, stderr) => {
if(error ?? stderr) {
if (debug) {
console.log(stdout)
}
console.log(stderr)
reject(error ?? stderr)
} else {
Expand Down
2 changes: 1 addition & 1 deletion sol/script/WinnerCalc.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Params, WinnerCalc, Winner } from "../src/WinnerCalc.sol";

contract WinnerCalcScript is Script {

WinnerCalc public winnerCalc;
WinnerCalc private winnerCalc;

function run() public {
string memory paramFilename = "files/params.txt";
Expand Down
2 changes: 1 addition & 1 deletion sol/src/WinnerCalc.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct Winner {

contract WinnerCalc {

Winner[] public winners;
Winner[] private winners;

/// @dev pushes winners to the `winners` array based off the prize param info
function checkWin(
Expand Down
15 changes: 11 additions & 4 deletions utils/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,29 @@ import { getPrizePoolInfo, getTierInfo, getVaultPortion } from "./prizePool.js"
import { getTwabs } from "./twab.js"
import type { Address } from "viem"

export const getAllParams = async (chainId: number, rpcUrl: string, prizePoolAddress: Address, vaultAddress: Address, userAddresses: Address[], options?: { multicallBatchSize?: number }) => {
export const getAllParams = async (chainId: number, rpcUrl: string, prizePoolAddress: Address, vaultAddress: Address, userAddresses: Address[], options?: { multicallBatchSize?: number, blockNumber?: bigint }) => {
const params: { tier: number, params: `0x${string}`, chunkSize: number, prizeCount: number }[] = []
const cachedTwabs: { [startTimestamp: number]: ReturnType<typeof getTwabs> } = {}

const client = getClient(chainId, rpcUrl, options)

const prizePoolInfo = await getPrizePoolInfo(client, prizePoolAddress)
const tierInfo = await getTierInfo(client, prizePoolAddress, prizePoolInfo.numTiers, prizePoolInfo.lastAwardedDrawId)
const prizePoolInfo = await getPrizePoolInfo(client, prizePoolAddress, options)
const tierInfo = await getTierInfo(client, prizePoolAddress, prizePoolInfo.numTiers, prizePoolInfo.lastAwardedDrawId, options)

await Promise.all(Object.keys(tierInfo).map(async (_tier) => {
const tier = parseInt(_tier)
const vaultPortion = await getVaultPortion(client, prizePoolAddress, vaultAddress, { start: tierInfo[tier].startTwabDrawId, end: prizePoolInfo.lastAwardedDrawId })

const startTwabTimestamp = tierInfo[tier].startTwabTimestamp
if(cachedTwabs[startTwabTimestamp] === undefined) {
cachedTwabs[startTwabTimestamp] = getTwabs(client, prizePoolInfo.twabControllerAddress, vaultAddress, userAddresses, { start: startTwabTimestamp, end: prizePoolInfo.lastAwardedDrawClosedAt })
cachedTwabs[startTwabTimestamp] = getTwabs(
client,
prizePoolInfo.twabControllerAddress,
vaultAddress,
userAddresses,
{ start: startTwabTimestamp, end: prizePoolInfo.lastAwardedDrawClosedAt },
options
)
}
const { vaultTwab, userTwabs } = await cachedTwabs[startTwabTimestamp]

Expand Down
11 changes: 6 additions & 5 deletions utils/prizePool.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { prizePoolABI } from "./abis/prizePool.js"
import type { Address, ContractFunctionParameters, PublicClient } from "viem"

export const getPrizePoolInfo = async (client: PublicClient, prizePoolAddress: Address) => {
export const getPrizePoolInfo = async (client: PublicClient, prizePoolAddress: Address, options?: { blockNumber?: bigint }) => {
const multicallResults = await client.multicall({
contracts: [
{ address: prizePoolAddress, abi: prizePoolABI, functionName: 'twabController' },
{ address: prizePoolAddress, abi: prizePoolABI, functionName: 'getWinningRandomNumber' },
{ address: prizePoolAddress, abi: prizePoolABI, functionName: 'getLastAwardedDrawId' },
{ address: prizePoolAddress, abi: prizePoolABI, functionName: 'numberOfTiers' }
]
],
blockNumber: options?.blockNumber
})

if(multicallResults.some(i => i.status === 'failure')) {
Expand All @@ -30,7 +31,7 @@ export const getPrizePoolInfo = async (client: PublicClient, prizePoolAddress: A
return { twabControllerAddress, randomNumber, lastAwardedDrawId, lastAwardedDrawClosedAt, numTiers }
}

export const getTierInfo = async (client: PublicClient, prizePoolAddress: Address, numTiers: number, lastAwardedDrawId: number) => {
export const getTierInfo = async (client: PublicClient, prizePoolAddress: Address, numTiers: number, lastAwardedDrawId: number, options?: { blockNumber?: bigint }) => {
const tierInfo: { [tier: number]: { prizeCount: number, odds: bigint, accrualDraws: number, startTwabDrawId: number, startTwabTimestamp: number } } = {}
const tiers = Array.from(Array(numTiers).keys())
const startDrawIds: { [tier: number]: number } = {}
Expand All @@ -42,7 +43,7 @@ export const getTierInfo = async (client: PublicClient, prizePoolAddress: Addres
firstContracts.push({ address: prizePoolAddress, abi: prizePoolABI, functionName: 'getTierAccrualDurationInDraws', args: [tier] })
})

const firstMulticallResults = await client.multicall({ contracts: firstContracts })
const firstMulticallResults = await client.multicall({ contracts: firstContracts, blockNumber: options?.blockNumber })

if(firstMulticallResults.some(i => i.status === 'failure')) {
throw new Error('Could not query basic tier information.')
Expand All @@ -55,7 +56,7 @@ export const getTierInfo = async (client: PublicClient, prizePoolAddress: Addres
secondContracts.push({ address: prizePoolAddress, abi: prizePoolABI, functionName: 'drawOpensAt', args: [startDrawIds[tier]] })
})

const secondMulticallResults = await client.multicall({ contracts: secondContracts })
const secondMulticallResults = await client.multicall({ contracts: secondContracts, blockNumber: options?.blockNumber })

if(secondMulticallResults.some(i => i.status === 'failure')) {
throw new Error('Could not query draw timestamps based on tier accrual duration.')
Expand Down
12 changes: 10 additions & 2 deletions utils/twab.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { twabControllerABI } from "./abis/twabController.js"
import type { Address, PublicClient } from "viem"

export const getTwabs = async (client: PublicClient, twabControllerAddress: Address, vaultAddress: Address, userAddresses: Address[], timestamps: { start: number, end: number }) => {
export const getTwabs = async (
client: PublicClient,
twabControllerAddress: Address,
vaultAddress: Address,
userAddresses: Address[],
timestamps: { start: number, end: number },
options?: { blockNumber?: bigint }
) => {
const userTwabs: { address: Address, twab: bigint }[] = []

const multicallResults = await client.multicall({
Expand All @@ -18,7 +25,8 @@ export const getTwabs = async (client: PublicClient, twabControllerAddress: Addr
functionName: 'getTwabBetween',
args: [vaultAddress, userAddress, BigInt(timestamps.start), BigInt(timestamps.end)]
}))
]
],
blockNumber: options?.blockNumber
})

if(multicallResults[0].status === 'failure') {
Expand Down

0 comments on commit 3016ee7

Please sign in to comment.