From 19c14a69ff4500d8c3e1dfb54ae238506f1ac07b Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Thu, 2 Oct 2025 14:01:46 +0200 Subject: [PATCH 1/3] migrates network:parameters to viem --- packages/actions/src/contract-name.ts | 2 + packages/actions/src/contracts/reserve.ts | 19 + .../actions/src/contracts/sorted-oracles.ts | 19 + .../cli/src/commands/network/parameters.ts | 5 +- packages/cli/src/utils/duration.ts | 51 +++ packages/cli/src/utils/network.ts | 374 ++++++++++++++++++ 6 files changed, 468 insertions(+), 2 deletions(-) create mode 100644 packages/actions/src/contracts/reserve.ts create mode 100644 packages/actions/src/contracts/sorted-oracles.ts create mode 100644 packages/cli/src/utils/duration.ts create mode 100644 packages/cli/src/utils/network.ts diff --git a/packages/actions/src/contract-name.ts b/packages/actions/src/contract-name.ts index 8cc6d34031..1d67808e47 100644 --- a/packages/actions/src/contract-name.ts +++ b/packages/actions/src/contract-name.ts @@ -9,7 +9,9 @@ export type ContractName = | 'Governance' | 'GoldToken' | 'LockedGold' + | 'Reserve' | 'ScoreManager' + | 'SortedOracles' | 'StableToken' | 'StableTokenEUR' | 'StableTokenBRL' diff --git a/packages/actions/src/contracts/reserve.ts b/packages/actions/src/contracts/reserve.ts new file mode 100644 index 0000000000..e4d14eda78 --- /dev/null +++ b/packages/actions/src/contracts/reserve.ts @@ -0,0 +1,19 @@ +import { reserveABI } from '@celo/abis' +import { Address, getContract, GetContractReturnType } from 'viem' +import { Clients } from '../client.js' +import { resolveAddress } from './registry.js' + +export type ReserveContract = GetContractReturnType< + typeof reserveABI, + T +> + +export async function getReserveContract( + clients: T +): Promise> { + return getContract({ + address: await resolveAddress(clients.public, 'Reserve'), + abi: reserveABI, + client: clients, + }) +} \ No newline at end of file diff --git a/packages/actions/src/contracts/sorted-oracles.ts b/packages/actions/src/contracts/sorted-oracles.ts new file mode 100644 index 0000000000..061c7d002a --- /dev/null +++ b/packages/actions/src/contracts/sorted-oracles.ts @@ -0,0 +1,19 @@ +import { sortedOraclesABI } from '@celo/abis' +import { Address, getContract, GetContractReturnType } from 'viem' +import { Clients } from '../client.js' +import { resolveAddress } from './registry.js' + +export type SortedOraclesContract = GetContractReturnType< + typeof sortedOraclesABI, + T +> + +export async function getSortedOraclesContract( + clients: T +): Promise> { + return getContract({ + address: await resolveAddress(clients.public, 'SortedOracles'), + abi: sortedOraclesABI, + client: clients, + }) +} \ No newline at end of file diff --git a/packages/cli/src/commands/network/parameters.ts b/packages/cli/src/commands/network/parameters.ts index f317841c1f..a93c070a92 100644 --- a/packages/cli/src/commands/network/parameters.ts +++ b/packages/cli/src/commands/network/parameters.ts @@ -2,6 +2,7 @@ import { Flags } from '@oclif/core' import { BaseCommand } from '../../base' import { printValueMapRecursive } from '../../utils/cli' import { ViewCommmandFlags } from '../../utils/flags' +import { getNetworkConfig } from '../../utils/network' export default class Parameters extends BaseCommand { static description = @@ -17,9 +18,9 @@ export default class Parameters extends BaseCommand { } async run() { - const kit = await this.getKit() + const client = await this.getPublicClient() const res = await this.parse(Parameters) - const config = await kit.getNetworkConfig(!res.flags.raw) + const config = await getNetworkConfig(client, !res.flags.raw) printValueMapRecursive(config) } } diff --git a/packages/cli/src/utils/duration.ts b/packages/cli/src/utils/duration.ts new file mode 100644 index 0000000000..d4bbae8fc7 --- /dev/null +++ b/packages/cli/src/utils/duration.ts @@ -0,0 +1,51 @@ +import BigNumber from 'bignumber.js' + +function valueToBigNumber(input: BigNumber.Value): BigNumber { + return new BigNumber(input.toString()) +} + +enum TimeDurations { + millennium = 31536000000000, + century = 3153600000000, + decade = 315360000000, + year = 31536000000, + quarter = 7776000000, + month = 2592000000, + week = 604800000, + day = 86400000, + hour = 3600000, + minute = 60000, + second = 1000, + millisecond = 1, +} + +type TimeUnit = keyof typeof TimeDurations + +// taken mostly from https://gist.github.com/RienNeVaPlus/024de3431ae95546d60f2acce128a7e2 +export function secondsToDurationString( + durationSeconds: BigNumber.Value, + outputUnits: TimeUnit[] = ['year', 'month', 'week', 'day', 'hour', 'minute', 'second'] +): string { + let durationMilliseconds = valueToBigNumber(durationSeconds) + .times(TimeDurations.second) + .toNumber() + if (durationMilliseconds <= 0) { + return 'past' + } + const durations = outputUnits.reduce((res: Map, key) => { + const unitDuration = TimeDurations[key] + const value = Math.floor(durationMilliseconds / unitDuration) + durationMilliseconds -= value * unitDuration + return res.set(key, value) + }, new Map()) + let s = '' + durations.forEach((value, unit) => { + if (value > 0) { + s += `${value} ${unit}${value !== 1 ? 's' : ''} ` + } + }) + return s.trim() +} + +export const blocksToDurationString = (input: BigNumber.Value): string => + secondsToDurationString(valueToBigNumber(input).times(1)) // Celo block time is 1 second \ No newline at end of file diff --git a/packages/cli/src/utils/network.ts b/packages/cli/src/utils/network.ts new file mode 100644 index 0000000000..18eb3af85f --- /dev/null +++ b/packages/cli/src/utils/network.ts @@ -0,0 +1,374 @@ +import { PublicCeloClient } from '@celo/actions' +import { getElectionContract } from '@celo/actions/contracts/election' +import { getGovernanceContract } from '@celo/actions/contracts/governance' +import { getLockedCeloContract } from '@celo/actions/contracts/locked-celo' +import { getFeeCurrencyDirectoryContract } from '@celo/actions/contracts/feecurrency-directory' +import { getEpochManagerContract } from '@celo/actions/contracts/epoch-manager' +import { getValidatorsContract } from '@celo/actions/contracts/validators' +import { getSortedOraclesContract } from '@celo/actions/contracts/sorted-oracles' +import { getReserveContract } from '@celo/actions/contracts/reserve' +import BigNumber from 'bignumber.js' +import { secondsToDurationString, blocksToDurationString } from './duration' + +// Specific types for each contract's config +export interface ElectionConfig { + electableValidators: { min: BigNumber; max: BigNumber } + electabilityThreshold: BigNumber + maxNumGroupsVotedFor: BigNumber + totalVotes: BigNumber + currentThreshold: BigNumber +} + +export interface GovernanceConfig { + concurrentProposals: BigNumber + dequeueFrequency: BigNumber + minDeposit: BigNumber + queueExpiry: BigNumber + stageDurations: { + approval: BigNumber + referendum: BigNumber + execution: BigNumber + } + participationParameters: { + baseline: BigNumber + baselineFloor: BigNumber + baselineUpdateFactor: BigNumber + baselineQuorumFactor: BigNumber + } +} + +export interface LockedGoldConfig { + unlockingPeriod: BigNumber + totalLockedGold: BigNumber +} + +export interface SortedOraclesConfig { + reportExpirySeconds: BigNumber +} + +export interface ReserveConfig { + tobinTaxStalenessThreshold: BigNumber + frozenReserveGoldStartBalance: BigNumber + frozenReserveGoldStartDay: BigNumber + frozenReserveGoldDays: BigNumber + otherReserveAddresses: readonly string[] +} + +export interface ValidatorsConfig { + validatorLockedGoldRequirements: { + value: BigNumber + duration: BigNumber + } + groupLockedGoldRequirements: { + value: BigNumber + duration: BigNumber + } + maxGroupSize: BigNumber + membershipHistoryLength: BigNumber + slashingMultiplierResetPeriod: BigNumber + commissionUpdateDelay: BigNumber + downtimeGracePeriod: BigNumber +} + +export interface EpochManagerConfig { + currentEpochNumber: BigNumber + epochDuration: BigNumber + isTimeForNextEpoch: boolean +} + +export interface FeeCurrencyDirectoryConfig { + // Empty object as per contractkit behavior +} + +export interface NetworkConfig { + Election?: ElectionConfig | Error + Governance?: GovernanceConfig | Error + LockedGold?: LockedGoldConfig | Error + SortedOracles?: SortedOraclesConfig | Error + Reserve?: ReserveConfig | Error + Validators?: ValidatorsConfig | Error + FeeCurrencyDirectory?: FeeCurrencyDirectoryConfig | Error + EpochManager?: EpochManagerConfig | Error +} + +function valueToBigNumber(input: string | number | bigint): BigNumber { + return new BigNumber(input.toString()) +} + +export async function getNetworkConfig( + client: PublicCeloClient, + humanReadable = false +): Promise { + const contractGetters = { + Election: () => getElectionContract({ public: client }), + Governance: () => getGovernanceContract({ public: client }), + LockedGold: () => getLockedCeloContract({ public: client }), + SortedOracles: () => getSortedOraclesContract({ public: client }), + Reserve: () => getReserveContract({ public: client }), + Validators: () => getValidatorsContract({ public: client }), + FeeCurrencyDirectory: () => getFeeCurrencyDirectoryContract({ public: client }), + EpochManager: () => getEpochManagerContract({ public: client }) + } + + const configMethod = async (contractName: keyof typeof contractGetters) => { + try { + const contract = await contractGetters[contractName]() + + if (humanReadable && contractName in humanReadableConfigs) { + return await humanReadableConfigs[contractName](contract) + } else if (contractName in configs) { + return await configs[contractName](contract) + } else { + throw new Error('No config endpoint found') + } + } catch (e) { + return new Error(`Failed to fetch config for contract ${contractName}: \n${e}`) + } + } + + const configArray = await Promise.all(Object.keys(contractGetters).map(k => configMethod(k as keyof typeof contractGetters))) + const configMap: NetworkConfig = {} + + Object.keys(contractGetters).forEach((contractName, index) => { + const result = configArray[index] + const key = contractName as keyof NetworkConfig + if (key === 'Election') { + configMap.Election = result as ElectionConfig | Error + } else if (key === 'Governance') { + configMap.Governance = result as GovernanceConfig | Error + } else if (key === 'LockedGold') { + configMap.LockedGold = result as LockedGoldConfig | Error + } else if (key === 'SortedOracles') { + configMap.SortedOracles = result as SortedOraclesConfig | Error + } else if (key === 'Reserve') { + configMap.Reserve = result as ReserveConfig | Error + } else if (key === 'Validators') { + configMap.Validators = result as ValidatorsConfig | Error + } else if (key === 'FeeCurrencyDirectory') { + configMap.FeeCurrencyDirectory = result as FeeCurrencyDirectoryConfig | Error + } else if (key === 'EpochManager') { + configMap.EpochManager = result as EpochManagerConfig | Error + } + }) + + return configMap +} + +// Exact replica of each contract's getConfig method +const configs: { + Election: (contract: Awaited>) => Promise + Governance: (contract: Awaited>) => Promise + LockedGold: (contract: Awaited>) => Promise + SortedOracles: (contract: Awaited>) => Promise + Reserve: (contract: Awaited>) => Promise + Validators: (contract: Awaited>) => Promise + FeeCurrencyDirectory: (contract: Awaited>) => Promise + EpochManager: (contract: Awaited>) => Promise +} = { + Election: async (contract: Awaited>): Promise => { + const [electableValidators, electabilityThreshold, maxNumGroupsVotedFor, totalVotes] = + await Promise.all([ + contract.read.getElectableValidators(), + contract.read.getElectabilityThreshold(), + contract.read.maxNumGroupsVotedFor(), + contract.read.getTotalVotes() + ]) + + const electableValidatorsResult = { min: valueToBigNumber(electableValidators[0]), max: valueToBigNumber(electableValidators[1]) } + const totalVotesResult = valueToBigNumber(totalVotes) + + return { + electableValidators: electableValidatorsResult, + electabilityThreshold: valueToBigNumber(electabilityThreshold), + maxNumGroupsVotedFor: valueToBigNumber(maxNumGroupsVotedFor), + totalVotes: totalVotesResult, + currentThreshold: totalVotesResult.multipliedBy(valueToBigNumber(electabilityThreshold)) + } + }, + + Governance: async (contract: Awaited>): Promise => { + const [concurrentProposals, dequeueFrequency, minDeposit, queueExpiry, stageDurations, participationParameters] = + await Promise.all([ + contract.read.concurrentProposals(), + contract.read.dequeueFrequency(), + contract.read.minDeposit(), + contract.read.queueExpiry(), + contract.read.stageDurations(), + contract.read.getParticipationParameters() + ]) + + return { + concurrentProposals: valueToBigNumber(concurrentProposals), + dequeueFrequency: valueToBigNumber(dequeueFrequency), + minDeposit: valueToBigNumber(minDeposit), + queueExpiry: valueToBigNumber(queueExpiry), + stageDurations: stageDurations ? { + approval: valueToBigNumber(stageDurations.approval || stageDurations[0]), + referendum: valueToBigNumber(stageDurations.referendum || stageDurations[1]), + execution: valueToBigNumber(stageDurations.execution || stageDurations[2]) + } : { approval: valueToBigNumber(0), referendum: valueToBigNumber(0), execution: valueToBigNumber(0) }, + participationParameters: participationParameters ? { + baseline: valueToBigNumber(participationParameters[0] || 0), + baselineFloor: valueToBigNumber(participationParameters[1] || 0), + baselineUpdateFactor: valueToBigNumber(participationParameters[2] || 0), + baselineQuorumFactor: valueToBigNumber(participationParameters[3] || 0) + } : { baseline: valueToBigNumber(0), baselineFloor: valueToBigNumber(0), baselineUpdateFactor: valueToBigNumber(0), baselineQuorumFactor: valueToBigNumber(0) } + } + }, + + LockedGold: async (contract: Awaited>): Promise => { + const [unlockingPeriod, totalLockedGold] = await Promise.all([ + contract.read.unlockingPeriod(), + contract.read.getTotalLockedGold() + ]) + + return { + unlockingPeriod: valueToBigNumber(unlockingPeriod), + totalLockedGold: valueToBigNumber(totalLockedGold) + } + }, + + SortedOracles: async (contract: Awaited>): Promise => { + const reportExpirySeconds = await contract.read.reportExpirySeconds() + + return { + reportExpirySeconds: valueToBigNumber(reportExpirySeconds) + } + }, + + Reserve: async (contract: Awaited>): Promise => { + const [ + tobinTaxStalenessThreshold, + frozenReserveGoldStartBalance, + frozenReserveGoldStartDay, + frozenReserveGoldDays, + otherReserveAddresses + ] = await Promise.all([ + contract.read.tobinTaxStalenessThreshold(), + contract.read.frozenReserveGoldStartBalance(), + contract.read.frozenReserveGoldStartDay(), + contract.read.frozenReserveGoldDays(), + contract.read.getOtherReserveAddresses() + ]) + + return { + tobinTaxStalenessThreshold: valueToBigNumber(tobinTaxStalenessThreshold), + frozenReserveGoldStartBalance: valueToBigNumber(frozenReserveGoldStartBalance), + frozenReserveGoldStartDay: valueToBigNumber(frozenReserveGoldStartDay), + frozenReserveGoldDays: valueToBigNumber(frozenReserveGoldDays), + otherReserveAddresses + } + }, + + Validators: async (contract: Awaited>): Promise => { + const [ + validatorLockedGoldRequirements, + groupLockedGoldRequirements, + maxGroupSize, + membershipHistoryLength, + slashingMultiplierResetPeriod, + commissionUpdateDelay, + downtimeGracePeriod + ] = await Promise.all([ + contract.read.getValidatorLockedGoldRequirements(), + contract.read.getGroupLockedGoldRequirements(), + contract.read.maxGroupSize(), + contract.read.membershipHistoryLength(), + contract.read.slashingMultiplierResetPeriod(), + contract.read.commissionUpdateDelay(), + contract.read.deprecated_downtimeGracePeriod() + ]) + + return { + validatorLockedGoldRequirements: { + value: valueToBigNumber(validatorLockedGoldRequirements[0]), + duration: valueToBigNumber(validatorLockedGoldRequirements[1]) + }, + groupLockedGoldRequirements: { + value: valueToBigNumber(groupLockedGoldRequirements[0]), + duration: valueToBigNumber(groupLockedGoldRequirements[1]) + }, + maxGroupSize: valueToBigNumber(maxGroupSize), + membershipHistoryLength: valueToBigNumber(membershipHistoryLength), + slashingMultiplierResetPeriod: valueToBigNumber(slashingMultiplierResetPeriod), + commissionUpdateDelay: valueToBigNumber(commissionUpdateDelay), + downtimeGracePeriod: valueToBigNumber(downtimeGracePeriod) + } + }, + + FeeCurrencyDirectory: async (_contract: Awaited>): Promise => { + // FeeCurrencyDirectory doesn't have a standard config method in contractkit + // Return empty object to match contractkit behavior + return {} + }, + + EpochManager: async (contract: Awaited>): Promise => { + const [currentEpochNumber, epochDuration, isTimeForNextEpoch] = await Promise.all([ + contract.read.getCurrentEpochNumber(), + contract.read.epochDuration(), + contract.read.isTimeForNextEpoch() + ]) + + return { + currentEpochNumber: valueToBigNumber(currentEpochNumber), + epochDuration: valueToBigNumber(epochDuration), + isTimeForNextEpoch + } + } +} + +// Human readable versions - convert durations to readable strings +const humanReadableConfigs = { + Election: configs.Election, // No duration fields to convert + + Governance: async (contract: Awaited>) => { + const config = await configs.Governance(contract) + return { + ...config, + stageDurations: { + approval: blocksToDurationString(config.stageDurations.approval), + referendum: blocksToDurationString(config.stageDurations.referendum), + execution: blocksToDurationString(config.stageDurations.execution) + } + } + }, + + LockedGold: async (contract: Awaited>) => { + const config = await configs.LockedGold(contract) + return { + ...config, + unlockingPeriod: secondsToDurationString(config.unlockingPeriod) + } + }, + + SortedOracles: async (contract: Awaited>) => { + const config = await configs.SortedOracles(contract) + return { + reportExpiry: secondsToDurationString(config.reportExpirySeconds) + } + }, + + Reserve: configs.Reserve, // No duration fields to convert + + Validators: async (contract: Awaited>) => { + const config = await configs.Validators(contract) + return { + ...config, + validatorLockedGoldRequirements: { + ...config.validatorLockedGoldRequirements, + duration: secondsToDurationString(config.validatorLockedGoldRequirements.duration) + }, + groupLockedGoldRequirements: { + ...config.groupLockedGoldRequirements, + duration: secondsToDurationString(config.groupLockedGoldRequirements.duration) + }, + slashingMultiplierResetPeriod: secondsToDurationString(config.slashingMultiplierResetPeriod), + commissionUpdateDelay: blocksToDurationString(config.commissionUpdateDelay), + downtimeGracePeriod: secondsToDurationString(config.downtimeGracePeriod) + } + }, + + FeeCurrencyDirectory: configs.FeeCurrencyDirectory, // No duration fields to convert + + EpochManager: configs.EpochManager // No duration fields to convert (currentEpochNumber and isTimeForNextEpoch are not durations) +} \ No newline at end of file From 85e3eb51ca56a51000b2a19590233f110c941bea Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Thu, 2 Oct 2025 14:29:56 +0200 Subject: [PATCH 2/3] fcd --- packages/actions/src/contracts/reserve.ts | 2 +- .../actions/src/contracts/sorted-oracles.ts | 2 +- packages/cli/src/utils/duration.ts | 2 +- packages/cli/src/utils/network.ts | 204 +++++++++++------- 4 files changed, 135 insertions(+), 75 deletions(-) diff --git a/packages/actions/src/contracts/reserve.ts b/packages/actions/src/contracts/reserve.ts index e4d14eda78..918bbbac79 100644 --- a/packages/actions/src/contracts/reserve.ts +++ b/packages/actions/src/contracts/reserve.ts @@ -16,4 +16,4 @@ export async function getReserveContract( abi: reserveABI, client: clients, }) -} \ No newline at end of file +} diff --git a/packages/actions/src/contracts/sorted-oracles.ts b/packages/actions/src/contracts/sorted-oracles.ts index 061c7d002a..abece49471 100644 --- a/packages/actions/src/contracts/sorted-oracles.ts +++ b/packages/actions/src/contracts/sorted-oracles.ts @@ -16,4 +16,4 @@ export async function getSortedOraclesContract( abi: sortedOraclesABI, client: clients, }) -} \ No newline at end of file +} diff --git a/packages/cli/src/utils/duration.ts b/packages/cli/src/utils/duration.ts index d4bbae8fc7..6c0595585e 100644 --- a/packages/cli/src/utils/duration.ts +++ b/packages/cli/src/utils/duration.ts @@ -48,4 +48,4 @@ export function secondsToDurationString( } export const blocksToDurationString = (input: BigNumber.Value): string => - secondsToDurationString(valueToBigNumber(input).times(1)) // Celo block time is 1 second \ No newline at end of file + secondsToDurationString(valueToBigNumber(input).times(1)) // Celo block time is 1 second diff --git a/packages/cli/src/utils/network.ts b/packages/cli/src/utils/network.ts index 18eb3af85f..e7274c559c 100644 --- a/packages/cli/src/utils/network.ts +++ b/packages/cli/src/utils/network.ts @@ -77,7 +77,9 @@ export interface EpochManagerConfig { } export interface FeeCurrencyDirectoryConfig { - // Empty object as per contractkit behavior + intrinsicGasForAlternativeFeeCurrency: { + [feeCurrencyAddress: string]: BigNumber + } } export interface NetworkConfig { @@ -107,7 +109,7 @@ export async function getNetworkConfig( Reserve: () => getReserveContract({ public: client }), Validators: () => getValidatorsContract({ public: client }), FeeCurrencyDirectory: () => getFeeCurrencyDirectoryContract({ public: client }), - EpochManager: () => getEpochManagerContract({ public: client }) + EpochManager: () => getEpochManagerContract({ public: client }), } const configMethod = async (contractName: keyof typeof contractGetters) => { @@ -126,9 +128,11 @@ export async function getNetworkConfig( } } - const configArray = await Promise.all(Object.keys(contractGetters).map(k => configMethod(k as keyof typeof contractGetters))) + const configArray = await Promise.all( + Object.keys(contractGetters).map((k) => configMethod(k as keyof typeof contractGetters)) + ) const configMap: NetworkConfig = {} - + Object.keys(contractGetters).forEach((contractName, index) => { const result = configArray[index] const key = contractName as keyof NetworkConfig @@ -154,27 +158,44 @@ export async function getNetworkConfig( return configMap } -// Exact replica of each contract's getConfig method +// Exact replica of each contract's getConfig method const configs: { Election: (contract: Awaited>) => Promise - Governance: (contract: Awaited>) => Promise - LockedGold: (contract: Awaited>) => Promise - SortedOracles: (contract: Awaited>) => Promise + Governance: ( + contract: Awaited> + ) => Promise + LockedGold: ( + contract: Awaited> + ) => Promise + SortedOracles: ( + contract: Awaited> + ) => Promise Reserve: (contract: Awaited>) => Promise - Validators: (contract: Awaited>) => Promise - FeeCurrencyDirectory: (contract: Awaited>) => Promise - EpochManager: (contract: Awaited>) => Promise + Validators: ( + contract: Awaited> + ) => Promise + FeeCurrencyDirectory: ( + contract: Awaited> + ) => Promise + EpochManager: ( + contract: Awaited> + ) => Promise } = { - Election: async (contract: Awaited>): Promise => { - const [electableValidators, electabilityThreshold, maxNumGroupsVotedFor, totalVotes] = + Election: async ( + contract: Awaited> + ): Promise => { + const [electableValidators, electabilityThreshold, maxNumGroupsVotedFor, totalVotes] = await Promise.all([ contract.read.getElectableValidators(), contract.read.getElectabilityThreshold(), contract.read.maxNumGroupsVotedFor(), - contract.read.getTotalVotes() + contract.read.getTotalVotes(), ]) - const electableValidatorsResult = { min: valueToBigNumber(electableValidators[0]), max: valueToBigNumber(electableValidators[1]) } + const electableValidatorsResult = { + min: valueToBigNumber(electableValidators[0]), + max: valueToBigNumber(electableValidators[1]), + } const totalVotesResult = valueToBigNumber(totalVotes) return { @@ -182,73 +203,100 @@ const configs: { electabilityThreshold: valueToBigNumber(electabilityThreshold), maxNumGroupsVotedFor: valueToBigNumber(maxNumGroupsVotedFor), totalVotes: totalVotesResult, - currentThreshold: totalVotesResult.multipliedBy(valueToBigNumber(electabilityThreshold)) + currentThreshold: totalVotesResult.multipliedBy(valueToBigNumber(electabilityThreshold)), } }, - Governance: async (contract: Awaited>): Promise => { - const [concurrentProposals, dequeueFrequency, minDeposit, queueExpiry, stageDurations, participationParameters] = - await Promise.all([ - contract.read.concurrentProposals(), - contract.read.dequeueFrequency(), - contract.read.minDeposit(), - contract.read.queueExpiry(), - contract.read.stageDurations(), - contract.read.getParticipationParameters() - ]) + Governance: async ( + contract: Awaited> + ): Promise => { + const [ + concurrentProposals, + dequeueFrequency, + minDeposit, + queueExpiry, + stageDurations, + participationParameters, + ] = await Promise.all([ + contract.read.concurrentProposals(), + contract.read.dequeueFrequency(), + contract.read.minDeposit(), + contract.read.queueExpiry(), + contract.read.stageDurations(), + contract.read.getParticipationParameters(), + ]) return { concurrentProposals: valueToBigNumber(concurrentProposals), dequeueFrequency: valueToBigNumber(dequeueFrequency), minDeposit: valueToBigNumber(minDeposit), queueExpiry: valueToBigNumber(queueExpiry), - stageDurations: stageDurations ? { - approval: valueToBigNumber(stageDurations.approval || stageDurations[0]), - referendum: valueToBigNumber(stageDurations.referendum || stageDurations[1]), - execution: valueToBigNumber(stageDurations.execution || stageDurations[2]) - } : { approval: valueToBigNumber(0), referendum: valueToBigNumber(0), execution: valueToBigNumber(0) }, - participationParameters: participationParameters ? { - baseline: valueToBigNumber(participationParameters[0] || 0), - baselineFloor: valueToBigNumber(participationParameters[1] || 0), - baselineUpdateFactor: valueToBigNumber(participationParameters[2] || 0), - baselineQuorumFactor: valueToBigNumber(participationParameters[3] || 0) - } : { baseline: valueToBigNumber(0), baselineFloor: valueToBigNumber(0), baselineUpdateFactor: valueToBigNumber(0), baselineQuorumFactor: valueToBigNumber(0) } + stageDurations: stageDurations + ? { + approval: valueToBigNumber(stageDurations.approval || stageDurations[0]), + referendum: valueToBigNumber(stageDurations.referendum || stageDurations[1]), + execution: valueToBigNumber(stageDurations.execution || stageDurations[2]), + } + : { + approval: valueToBigNumber(0), + referendum: valueToBigNumber(0), + execution: valueToBigNumber(0), + }, + participationParameters: participationParameters + ? { + baseline: valueToBigNumber(participationParameters[0] || 0), + baselineFloor: valueToBigNumber(participationParameters[1] || 0), + baselineUpdateFactor: valueToBigNumber(participationParameters[2] || 0), + baselineQuorumFactor: valueToBigNumber(participationParameters[3] || 0), + } + : { + baseline: valueToBigNumber(0), + baselineFloor: valueToBigNumber(0), + baselineUpdateFactor: valueToBigNumber(0), + baselineQuorumFactor: valueToBigNumber(0), + }, } }, - LockedGold: async (contract: Awaited>): Promise => { + LockedGold: async ( + contract: Awaited> + ): Promise => { const [unlockingPeriod, totalLockedGold] = await Promise.all([ contract.read.unlockingPeriod(), - contract.read.getTotalLockedGold() + contract.read.getTotalLockedGold(), ]) return { unlockingPeriod: valueToBigNumber(unlockingPeriod), - totalLockedGold: valueToBigNumber(totalLockedGold) + totalLockedGold: valueToBigNumber(totalLockedGold), } }, - SortedOracles: async (contract: Awaited>): Promise => { + SortedOracles: async ( + contract: Awaited> + ): Promise => { const reportExpirySeconds = await contract.read.reportExpirySeconds() - + return { - reportExpirySeconds: valueToBigNumber(reportExpirySeconds) + reportExpirySeconds: valueToBigNumber(reportExpirySeconds), } }, - Reserve: async (contract: Awaited>): Promise => { + Reserve: async ( + contract: Awaited> + ): Promise => { const [ tobinTaxStalenessThreshold, - frozenReserveGoldStartBalance, + frozenReserveGoldStartBalance, frozenReserveGoldStartDay, frozenReserveGoldDays, - otherReserveAddresses + otherReserveAddresses, ] = await Promise.all([ contract.read.tobinTaxStalenessThreshold(), contract.read.frozenReserveGoldStartBalance(), contract.read.frozenReserveGoldStartDay(), contract.read.frozenReserveGoldDays(), - contract.read.getOtherReserveAddresses() + contract.read.getOtherReserveAddresses(), ]) return { @@ -256,11 +304,13 @@ const configs: { frozenReserveGoldStartBalance: valueToBigNumber(frozenReserveGoldStartBalance), frozenReserveGoldStartDay: valueToBigNumber(frozenReserveGoldStartDay), frozenReserveGoldDays: valueToBigNumber(frozenReserveGoldDays), - otherReserveAddresses + otherReserveAddresses, } }, - Validators: async (contract: Awaited>): Promise => { + Validators: async ( + contract: Awaited> + ): Promise => { const [ validatorLockedGoldRequirements, groupLockedGoldRequirements, @@ -268,7 +318,7 @@ const configs: { membershipHistoryLength, slashingMultiplierResetPeriod, commissionUpdateDelay, - downtimeGracePeriod + downtimeGracePeriod, ] = await Promise.all([ contract.read.getValidatorLockedGoldRequirements(), contract.read.getGroupLockedGoldRequirements(), @@ -276,45 +326,55 @@ const configs: { contract.read.membershipHistoryLength(), contract.read.slashingMultiplierResetPeriod(), contract.read.commissionUpdateDelay(), - contract.read.deprecated_downtimeGracePeriod() + contract.read.deprecated_downtimeGracePeriod(), ]) return { validatorLockedGoldRequirements: { value: valueToBigNumber(validatorLockedGoldRequirements[0]), - duration: valueToBigNumber(validatorLockedGoldRequirements[1]) + duration: valueToBigNumber(validatorLockedGoldRequirements[1]), }, groupLockedGoldRequirements: { value: valueToBigNumber(groupLockedGoldRequirements[0]), - duration: valueToBigNumber(groupLockedGoldRequirements[1]) + duration: valueToBigNumber(groupLockedGoldRequirements[1]), }, maxGroupSize: valueToBigNumber(maxGroupSize), membershipHistoryLength: valueToBigNumber(membershipHistoryLength), slashingMultiplierResetPeriod: valueToBigNumber(slashingMultiplierResetPeriod), commissionUpdateDelay: valueToBigNumber(commissionUpdateDelay), - downtimeGracePeriod: valueToBigNumber(downtimeGracePeriod) + downtimeGracePeriod: valueToBigNumber(downtimeGracePeriod), } }, - FeeCurrencyDirectory: async (_contract: Awaited>): Promise => { - // FeeCurrencyDirectory doesn't have a standard config method in contractkit - // Return empty object to match contractkit behavior - return {} + FeeCurrencyDirectory: async ( + contract: Awaited> + ): Promise => { + const addresses = await contract.read.getCurrencies() + const config: FeeCurrencyDirectoryConfig = { intrinsicGasForAlternativeFeeCurrency: {} } + + for (const address of addresses) { + const currencyConfig = await contract.read.getCurrencyConfig([address]) + config.intrinsicGasForAlternativeFeeCurrency[address] = valueToBigNumber(currencyConfig.intrinsicGas) + } + + return config }, - EpochManager: async (contract: Awaited>): Promise => { + EpochManager: async ( + contract: Awaited> + ): Promise => { const [currentEpochNumber, epochDuration, isTimeForNextEpoch] = await Promise.all([ contract.read.getCurrentEpochNumber(), contract.read.epochDuration(), - contract.read.isTimeForNextEpoch() + contract.read.isTimeForNextEpoch(), ]) return { currentEpochNumber: valueToBigNumber(currentEpochNumber), epochDuration: valueToBigNumber(epochDuration), - isTimeForNextEpoch + isTimeForNextEpoch, } - } + }, } // Human readable versions - convert durations to readable strings @@ -328,8 +388,8 @@ const humanReadableConfigs = { stageDurations: { approval: blocksToDurationString(config.stageDurations.approval), referendum: blocksToDurationString(config.stageDurations.referendum), - execution: blocksToDurationString(config.stageDurations.execution) - } + execution: blocksToDurationString(config.stageDurations.execution), + }, } }, @@ -337,14 +397,14 @@ const humanReadableConfigs = { const config = await configs.LockedGold(contract) return { ...config, - unlockingPeriod: secondsToDurationString(config.unlockingPeriod) + unlockingPeriod: secondsToDurationString(config.unlockingPeriod), } }, SortedOracles: async (contract: Awaited>) => { const config = await configs.SortedOracles(contract) return { - reportExpiry: secondsToDurationString(config.reportExpirySeconds) + reportExpiry: secondsToDurationString(config.reportExpirySeconds), } }, @@ -356,19 +416,19 @@ const humanReadableConfigs = { ...config, validatorLockedGoldRequirements: { ...config.validatorLockedGoldRequirements, - duration: secondsToDurationString(config.validatorLockedGoldRequirements.duration) + duration: secondsToDurationString(config.validatorLockedGoldRequirements.duration), }, groupLockedGoldRequirements: { ...config.groupLockedGoldRequirements, - duration: secondsToDurationString(config.groupLockedGoldRequirements.duration) + duration: secondsToDurationString(config.groupLockedGoldRequirements.duration), }, slashingMultiplierResetPeriod: secondsToDurationString(config.slashingMultiplierResetPeriod), commissionUpdateDelay: blocksToDurationString(config.commissionUpdateDelay), - downtimeGracePeriod: secondsToDurationString(config.downtimeGracePeriod) + downtimeGracePeriod: secondsToDurationString(config.downtimeGracePeriod), } }, FeeCurrencyDirectory: configs.FeeCurrencyDirectory, // No duration fields to convert - - EpochManager: configs.EpochManager // No duration fields to convert (currentEpochNumber and isTimeForNextEpoch are not durations) -} \ No newline at end of file + + EpochManager: configs.EpochManager, // No duration fields to convert (currentEpochNumber and isTimeForNextEpoch are not durations) +} From 55441e3dc60163361cb997b1d07c80a2ab6c1501 Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Thu, 2 Oct 2025 17:26:38 +0200 Subject: [PATCH 3/3] some values were still assuming 5 second block time --- .../src/commands/network/parameters.test.ts | 12 +- packages/cli/src/utils/network.ts | 166 ++++++++++-------- 2 files changed, 96 insertions(+), 82 deletions(-) diff --git a/packages/cli/src/commands/network/parameters.test.ts b/packages/cli/src/commands/network/parameters.test.ts index 70f319e1f8..9e2e6ece6c 100644 --- a/packages/cli/src/commands/network/parameters.test.ts +++ b/packages/cli/src/commands/network/parameters.test.ts @@ -20,8 +20,8 @@ testWithAnvilL2('network:parameters', (web3) => { maxNumGroupsVotedFor: 10 totalVotes: 60000000000000000000000 (~6.000e+22) EpochManager: - currentEpochNumber: 4 - epochDuration: 86400 + currentEpochNumber: 4 + epochDuration: 86400 (~8.640e+4) isTimeForNextEpoch: false FeeCurrencyDirectory: intrinsicGasForAlternativeFeeCurrency: @@ -42,7 +42,7 @@ testWithAnvilL2('network:parameters', (web3) => { Execution: 1 week Referendum: 1 day LockedCelo: - totalLockedGold: 120000000000000000000000 (~1.200e+23) + totalLockedCelo: 120000000000000000000000 (~1.200e+23) unlockingPeriod: 6 hours Reserve: frozenReserveGoldDays: 0 @@ -54,15 +54,15 @@ testWithAnvilL2('network:parameters', (web3) => { SortedOracles: reportExpiry: 5 minutes Validators: - commissionUpdateDelay: 3 days + commissionUpdateDelay: 14 hours 24 minutes downtimeGracePeriod: 0 - groupLockedGoldRequirements: + groupLockedCeloRequirements: duration: 6 months value: 10000000000000000000000 (~1.000e+22) maxGroupSize: 2 membershipHistoryLength: 60 slashingMultiplierResetPeriod: 1 month - validatorLockedGoldRequirements: + validatorLockedCeloRequirements: duration: 2 months value: 10000000000000000000000 (~1.000e+22)", ], diff --git a/packages/cli/src/utils/network.ts b/packages/cli/src/utils/network.ts index e7274c559c..98478f2f8f 100644 --- a/packages/cli/src/utils/network.ts +++ b/packages/cli/src/utils/network.ts @@ -1,14 +1,14 @@ import { PublicCeloClient } from '@celo/actions' -import { getElectionContract } from '@celo/actions/contracts/election' -import { getGovernanceContract } from '@celo/actions/contracts/governance' -import { getLockedCeloContract } from '@celo/actions/contracts/locked-celo' -import { getFeeCurrencyDirectoryContract } from '@celo/actions/contracts/feecurrency-directory' -import { getEpochManagerContract } from '@celo/actions/contracts/epoch-manager' -import { getValidatorsContract } from '@celo/actions/contracts/validators' -import { getSortedOraclesContract } from '@celo/actions/contracts/sorted-oracles' -import { getReserveContract } from '@celo/actions/contracts/reserve' +import { ElectionContract, getElectionContract } from '@celo/actions/contracts/election' +import { EpochManager, getEpochManagerContract } from '@celo/actions/contracts/epoch-manager' +import { FeeCurrencyDirectory, getFeeCurrencyDirectoryContract } from '@celo/actions/contracts/feecurrency-directory' +import { getGovernanceContract, GovernanceContract } from '@celo/actions/contracts/governance' +import { getLockedCeloContract, LockedCeloContract } from '@celo/actions/contracts/locked-celo' +import { getReserveContract, ReserveContract } from '@celo/actions/contracts/reserve' +import { getSortedOraclesContract, SortedOraclesContract } from '@celo/actions/contracts/sorted-oracles' +import { getValidatorsContract, ValidatorsContract } from '@celo/actions/contracts/validators' import BigNumber from 'bignumber.js' -import { secondsToDurationString, blocksToDurationString } from './duration' +import { blocksToDurationString, secondsToDurationString } from './duration' // Specific types for each contract's config export interface ElectionConfig { @@ -37,9 +37,9 @@ export interface GovernanceConfig { } } -export interface LockedGoldConfig { +export interface LockedCeloConfig { unlockingPeriod: BigNumber - totalLockedGold: BigNumber + totalLockedCelo: BigNumber } export interface SortedOraclesConfig { @@ -55,11 +55,11 @@ export interface ReserveConfig { } export interface ValidatorsConfig { - validatorLockedGoldRequirements: { + validatorLockedCeloRequirements: { value: BigNumber duration: BigNumber } - groupLockedGoldRequirements: { + groupLockedCeloRequirements: { value: BigNumber duration: BigNumber } @@ -85,7 +85,7 @@ export interface FeeCurrencyDirectoryConfig { export interface NetworkConfig { Election?: ElectionConfig | Error Governance?: GovernanceConfig | Error - LockedGold?: LockedGoldConfig | Error + LockedCelo?: LockedCeloConfig | Error SortedOracles?: SortedOraclesConfig | Error Reserve?: ReserveConfig | Error Validators?: ValidatorsConfig | Error @@ -97,6 +97,11 @@ function valueToBigNumber(input: string | number | bigint): BigNumber { return new BigNumber(input.toString()) } +function fixidityValueToBigNumber(input: string | number | bigint): BigNumber { + const FIXED1 = new BigNumber('1000000000000000000000000') // 10^24 + return new BigNumber(input.toString()).dividedBy(FIXED1) +} + export async function getNetworkConfig( client: PublicCeloClient, humanReadable = false @@ -104,7 +109,7 @@ export async function getNetworkConfig( const contractGetters = { Election: () => getElectionContract({ public: client }), Governance: () => getGovernanceContract({ public: client }), - LockedGold: () => getLockedCeloContract({ public: client }), + LockedCelo: () => getLockedCeloContract({ public: client }), SortedOracles: () => getSortedOraclesContract({ public: client }), Reserve: () => getReserveContract({ public: client }), Validators: () => getValidatorsContract({ public: client }), @@ -119,6 +124,7 @@ export async function getNetworkConfig( if (humanReadable && contractName in humanReadableConfigs) { return await humanReadableConfigs[contractName](contract) } else if (contractName in configs) { + // @ts-expect-error return await configs[contractName](contract) } else { throw new Error('No config endpoint found') @@ -140,8 +146,8 @@ export async function getNetworkConfig( configMap.Election = result as ElectionConfig | Error } else if (key === 'Governance') { configMap.Governance = result as GovernanceConfig | Error - } else if (key === 'LockedGold') { - configMap.LockedGold = result as LockedGoldConfig | Error + } else if (key === 'LockedCelo') { + configMap.LockedCelo = result as LockedCeloConfig | Error } else if (key === 'SortedOracles') { configMap.SortedOracles = result as SortedOraclesConfig | Error } else if (key === 'Reserve') { @@ -160,29 +166,29 @@ export async function getNetworkConfig( // Exact replica of each contract's getConfig method const configs: { - Election: (contract: Awaited>) => Promise + Election: (contract: ElectionContract) => Promise Governance: ( - contract: Awaited> + contract: GovernanceContract ) => Promise - LockedGold: ( - contract: Awaited> - ) => Promise + LockedCelo: ( + contract: LockedCeloContract + ) => Promise SortedOracles: ( - contract: Awaited> + contract: SortedOraclesContract ) => Promise - Reserve: (contract: Awaited>) => Promise + Reserve: (contract: ReserveContract) => Promise Validators: ( - contract: Awaited> + contract: ValidatorsContract ) => Promise FeeCurrencyDirectory: ( - contract: Awaited> + contract: FeeCurrencyDirectory ) => Promise EpochManager: ( - contract: Awaited> + contract: EpochManager ) => Promise } = { Election: async ( - contract: Awaited> + contract: ElectionContract ): Promise => { const [electableValidators, electabilityThreshold, maxNumGroupsVotedFor, totalVotes] = await Promise.all([ @@ -198,17 +204,19 @@ const configs: { } const totalVotesResult = valueToBigNumber(totalVotes) + const electabilityThresholdResult = fixidityValueToBigNumber(electabilityThreshold) + return { electableValidators: electableValidatorsResult, - electabilityThreshold: valueToBigNumber(electabilityThreshold), + electabilityThreshold: electabilityThresholdResult, maxNumGroupsVotedFor: valueToBigNumber(maxNumGroupsVotedFor), totalVotes: totalVotesResult, - currentThreshold: totalVotesResult.multipliedBy(valueToBigNumber(electabilityThreshold)), + currentThreshold: totalVotesResult.multipliedBy(electabilityThresholdResult), } }, Governance: async ( - contract: Awaited> + contract: GovernanceContract ): Promise => { const [ concurrentProposals, @@ -233,9 +241,9 @@ const configs: { queueExpiry: valueToBigNumber(queueExpiry), stageDurations: stageDurations ? { - approval: valueToBigNumber(stageDurations.approval || stageDurations[0]), - referendum: valueToBigNumber(stageDurations.referendum || stageDurations[1]), - execution: valueToBigNumber(stageDurations.execution || stageDurations[2]), + approval: valueToBigNumber( stageDurations[0]), + referendum: valueToBigNumber(stageDurations[1]), + execution: valueToBigNumber(stageDurations[2]), } : { approval: valueToBigNumber(0), @@ -244,36 +252,36 @@ const configs: { }, participationParameters: participationParameters ? { - baseline: valueToBigNumber(participationParameters[0] || 0), - baselineFloor: valueToBigNumber(participationParameters[1] || 0), - baselineUpdateFactor: valueToBigNumber(participationParameters[2] || 0), - baselineQuorumFactor: valueToBigNumber(participationParameters[3] || 0), + baseline: fixidityValueToBigNumber(participationParameters[0] || 0), + baselineFloor: fixidityValueToBigNumber(participationParameters[1] || 0), + baselineUpdateFactor: fixidityValueToBigNumber(participationParameters[2] || 0), + baselineQuorumFactor: fixidityValueToBigNumber(participationParameters[3] || 0), } : { - baseline: valueToBigNumber(0), - baselineFloor: valueToBigNumber(0), - baselineUpdateFactor: valueToBigNumber(0), - baselineQuorumFactor: valueToBigNumber(0), + baseline: fixidityValueToBigNumber(0), + baselineFloor: fixidityValueToBigNumber(0), + baselineUpdateFactor: fixidityValueToBigNumber(0), + baselineQuorumFactor: fixidityValueToBigNumber(0), }, } }, - LockedGold: async ( - contract: Awaited> - ): Promise => { - const [unlockingPeriod, totalLockedGold] = await Promise.all([ + LockedCelo: async ( + contract: LockedCeloContract + ): Promise => { + const [unlockingPeriod, totalLockedCelo] = await Promise.all([ contract.read.unlockingPeriod(), contract.read.getTotalLockedGold(), ]) return { unlockingPeriod: valueToBigNumber(unlockingPeriod), - totalLockedGold: valueToBigNumber(totalLockedGold), + totalLockedCelo: valueToBigNumber(totalLockedCelo), } }, SortedOracles: async ( - contract: Awaited> + contract: SortedOraclesContract ): Promise => { const reportExpirySeconds = await contract.read.reportExpirySeconds() @@ -309,11 +317,11 @@ const configs: { }, Validators: async ( - contract: Awaited> + contract: ValidatorsContract ): Promise => { const [ - validatorLockedGoldRequirements, - groupLockedGoldRequirements, + validatorLockedCeloRequirements, + groupLockedCeloRequirements, maxGroupSize, membershipHistoryLength, slashingMultiplierResetPeriod, @@ -330,13 +338,13 @@ const configs: { ]) return { - validatorLockedGoldRequirements: { - value: valueToBigNumber(validatorLockedGoldRequirements[0]), - duration: valueToBigNumber(validatorLockedGoldRequirements[1]), + validatorLockedCeloRequirements: { + value: valueToBigNumber(validatorLockedCeloRequirements[0]), + duration: valueToBigNumber(validatorLockedCeloRequirements[1]), }, - groupLockedGoldRequirements: { - value: valueToBigNumber(groupLockedGoldRequirements[0]), - duration: valueToBigNumber(groupLockedGoldRequirements[1]), + groupLockedCeloRequirements: { + value: valueToBigNumber(groupLockedCeloRequirements[0]), + duration: valueToBigNumber(groupLockedCeloRequirements[1]), }, maxGroupSize: valueToBigNumber(maxGroupSize), membershipHistoryLength: valueToBigNumber(membershipHistoryLength), @@ -354,7 +362,9 @@ const configs: { for (const address of addresses) { const currencyConfig = await contract.read.getCurrencyConfig([address]) - config.intrinsicGasForAlternativeFeeCurrency[address] = valueToBigNumber(currencyConfig.intrinsicGas) + config.intrinsicGasForAlternativeFeeCurrency[address] = valueToBigNumber( + currencyConfig.intrinsicGas + ) } return config @@ -379,22 +389,26 @@ const configs: { // Human readable versions - convert durations to readable strings const humanReadableConfigs = { - Election: configs.Election, // No duration fields to convert + Election: configs.Election, - Governance: async (contract: Awaited>) => { + Governance: async (contract: GovernanceContract) => { const config = await configs.Governance(contract) return { ...config, + dequeueFrequency: secondsToDurationString(config.dequeueFrequency), + participationParameters: { + ...config.participationParameters, + }, + queueExpiry: secondsToDurationString(config.queueExpiry), stageDurations: { - approval: blocksToDurationString(config.stageDurations.approval), - referendum: blocksToDurationString(config.stageDurations.referendum), - execution: blocksToDurationString(config.stageDurations.execution), + Execution: blocksToDurationString(config.stageDurations.execution), + Referendum: blocksToDurationString(config.stageDurations.referendum), }, } }, - LockedGold: async (contract: Awaited>) => { - const config = await configs.LockedGold(contract) + LockedCelo: async (contract: LockedCeloContract) => { + const config = await configs.LockedCelo(contract) return { ...config, unlockingPeriod: secondsToDurationString(config.unlockingPeriod), @@ -410,25 +424,25 @@ const humanReadableConfigs = { Reserve: configs.Reserve, // No duration fields to convert - Validators: async (contract: Awaited>) => { + Validators: async (contract: ValidatorsContract) => { const config = await configs.Validators(contract) return { ...config, - validatorLockedGoldRequirements: { - ...config.validatorLockedGoldRequirements, - duration: secondsToDurationString(config.validatorLockedGoldRequirements.duration), + validatorLockedCeloRequirements: { + ...config.validatorLockedCeloRequirements, + duration: secondsToDurationString(config.validatorLockedCeloRequirements.duration), }, - groupLockedGoldRequirements: { - ...config.groupLockedGoldRequirements, - duration: secondsToDurationString(config.groupLockedGoldRequirements.duration), + groupLockedCeloRequirements: { + ...config.groupLockedCeloRequirements, + duration: secondsToDurationString(config.groupLockedCeloRequirements.duration), }, slashingMultiplierResetPeriod: secondsToDurationString(config.slashingMultiplierResetPeriod), - commissionUpdateDelay: blocksToDurationString(config.commissionUpdateDelay), - downtimeGracePeriod: secondsToDurationString(config.downtimeGracePeriod), + commissionUpdateDelay: secondsToDurationString(config.commissionUpdateDelay), + downtimeGracePeriod: config.downtimeGracePeriod, } }, - FeeCurrencyDirectory: configs.FeeCurrencyDirectory, // No duration fields to convert + FeeCurrencyDirectory: configs.FeeCurrencyDirectory, - EpochManager: configs.EpochManager, // No duration fields to convert (currentEpochNumber and isTimeForNextEpoch are not durations) + EpochManager: configs.EpochManager, }