Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: calculate arbitrum block number for start of epoch #71

Merged
merged 6 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions apps/agent/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,19 @@ import { config } from "./config/index.js";
const logger = Logger.getInstance();

const main = async (): Promise<void> => {
const protocolProvider = new ProtocolProvider(
config.protocolProvider.rpcsConfig,
config.protocolProvider.contracts,
config.protocolProvider.privateKey,
);

const blockNumberService = new BlockNumberService(
config.blockNumberService.chainRpcUrls,
config.blockNumberService.blockmetaConfig,
logger,
);

const protocolProvider = new ProtocolProvider(
config.protocolProvider.rpcsConfig,
config.protocolProvider.contracts,
config.protocolProvider.privateKey,
blockNumberService,
);

const actorsManager = new EboActorsManager();

const notifier = await DiscordNotifier.create(
Expand Down
17 changes: 16 additions & 1 deletion apps/scripts/utilities/approveAccountingModules.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ProtocolProvider } from "@ebo-agent/automated-dispute/src/index.js";
import { BlockNumberService } from "@ebo-agent/blocknumber";
import { Caip2ChainId } from "@ebo-agent/shared";
import * as dotenv from "dotenv";
import { Address, Hex, isHex } from "viem";
Expand Down Expand Up @@ -100,9 +101,23 @@ const rpcConfig = {
},
};

/**
* Mocking the BlockNumberService since we don't need it for the script
*/
const mockBlockNumberService = {
getEpochBlockNumber: async () => {
return 0n;
},
} as unknown as BlockNumberService;

const contracts = env.CONTRACTS_ADDRESSES;

const provider = new ProtocolProvider(rpcConfig, contracts, env.PRIVATE_KEY as Hex);
const provider = new ProtocolProvider(
rpcConfig,
contracts,
env.PRIVATE_KEY as Hex,
mockBlockNumberService,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to drop this with the new changes! I think you'll need to add the optionality for BlockNumberService in the ProtocolProvider constructor

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops this got filtered out in the merge

);

/**
* Approves the necessary modules by calling approveModule on ProtocolProvider.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export class BlockNumberServiceRequiredError extends Error {
constructor() {
super("BlockNumberService is required to get the current epoch");
this.name = "BlockNumberServiceRequiredError";
}
}
1 change: 1 addition & 0 deletions packages/automated-dispute/src/exceptions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ export * from "./invalidBlockRangeError.exception.js";
export * from "./unknownCustomError.exception.js";
export * from "./invalidBlockHash.exception.js";
export * from "./unknownDisputeStatus.exception.js";
export * from "./blockNumberServiceRequired.exception.js";
export * from "./customContractError.js";
export * from "./errorFactory.js";
23 changes: 20 additions & 3 deletions packages/automated-dispute/src/providers/protocolProvider.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UnsupportedChain } from "@ebo-agent/blocknumber";
import { BlockNumberService, UnsupportedChain } from "@ebo-agent/blocknumber";
import { Caip2ChainId, HexUtils, UnixTimestamp } from "@ebo-agent/shared";
import {
Address,
Expand Down Expand Up @@ -41,6 +41,7 @@ import {
oracleAbi,
} from "../abis/index.js";
import {
BlockNumberServiceRequiredError,
ErrorFactory,
InvalidAccountOnClient,
InvalidBlockHashError,
Expand Down Expand Up @@ -75,6 +76,7 @@ export class ProtocolProvider implements IProtocolProvider {
private l1ReadClient: PublicClient<FallbackTransport<HttpTransport[]>>;
private l2ReadClient: PublicClient<FallbackTransport<HttpTransport[]>>;
private l2WriteClient: WalletClient<FallbackTransport<HttpTransport[]>>;
private readonly blockNumberService?: BlockNumberService;

private oracleContract: GetContractReturnType<
typeof oracleAbi,
Expand Down Expand Up @@ -111,18 +113,21 @@ export class ProtocolProvider implements IProtocolProvider {
* @param rpcConfig The configuration for RPC connections including URLs, timeout, retry interval, and transaction receipt confirmations
* @param contracts The addresses of the protocol contracts that will be instantiated
* @param privateKey The private key of the account that will be used to interact with the contracts
* @param blockNumberService The service that will be used to fetch block numbers
*/
constructor(
private readonly rpcConfig: ProtocolRpcConfig,
contracts: ProtocolContractsAddresses,
privateKey: Hex,
blockNumberService: BlockNumberService,
) {
const l1Chain = this.getViemChain(rpcConfig.l1.chainId);
const l2Chain = this.getViemChain(rpcConfig.l2.chainId);

this.l1ReadClient = this.createReadClient(rpcConfig.l1, l1Chain);
this.l2ReadClient = this.createReadClient(rpcConfig.l2, l2Chain);
this.l2WriteClient = this.createWriteClient(rpcConfig.l2, l2Chain, privateKey);
this.blockNumberService = blockNumberService;

// Instantiate all the protocol contracts
this.oracleContract = getContract({
Expand Down Expand Up @@ -269,6 +274,10 @@ export class ProtocolProvider implements IProtocolProvider {
* @returns {Promise<Epoch>} The current epoch, its block number, and its timestamp.
*/
async getCurrentEpoch(): Promise<Epoch> {
if (!this.blockNumberService) {
throw new BlockNumberServiceRequiredError();
}

const [epoch, epochFirstBlockNumber] = await Promise.all([
this.epochManagerContract.read.currentEpoch(),
this.epochManagerContract.read.currentEpochBlock(),
Expand All @@ -278,10 +287,18 @@ export class ProtocolProvider implements IProtocolProvider {
blockNumber: epochFirstBlockNumber,
});

const startTimestamp = epochFirstBlock.timestamp as UnixTimestamp;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make the blockNumberService dependency optional so we don't have to worry about creating a mocked version of it within the recently developed scripts. Let's make it so ProtocolProvider fails if someone tries to get a current epoch without passing a block number service when initializing it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


const l2ChainId = this.rpcConfig.l2.chainId;
const l2FirstBlockNumber = await this.blockNumberService.getEpochBlockNumber(
startTimestamp,
l2ChainId,
);

return {
number: epoch,
firstBlockNumber: epochFirstBlockNumber,
startTimestamp: epochFirstBlock.timestamp as UnixTimestamp,
firstBlockNumber: l2FirstBlockNumber,
startTimestamp: startTimestamp,
};
}

Expand Down
43 changes: 23 additions & 20 deletions packages/automated-dispute/tests/mocks/eboProcessor.mocks.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { BlockNumberService, Caip2ChainId } from "@ebo-agent/blocknumber";
import { ILogger } from "@ebo-agent/shared";
import { BlockNumberService } from "@ebo-agent/blocknumber";
import { Caip2ChainId, ILogger } from "@ebo-agent/shared";
import { vi } from "vitest";

import { NotificationService } from "../../src/index.js";
import { ProtocolProvider } from "../../src/providers/index.js";
import { EboProcessor, NotificationService } from "../../src/services";
import { EboProcessor } from "../../src/services";
import { EboActorsManager } from "../../src/services/index.js";
import { AccountingModules } from "../../src/types/prophet.js";
import {
Expand All @@ -20,6 +21,24 @@ export function buildEboProcessor(
},
notifier?: NotificationService,
) {
const blockNumberRpcUrls = new Map<Caip2ChainId, string[]>([
["eip155:1" as Caip2ChainId, ["http://localhost:8539"]],
]);

const blockNumberService = new BlockNumberService(
blockNumberRpcUrls,
{
baseUrl: new URL("http://localhost"),
bearerToken: "secret-token",
bearerTokenExpirationWindow: 10,
servicePaths: {
block: "/block",
blockByTime: "/blockbytime",
},
},
logger,
);

const protocolProvider = new ProtocolProvider(
{
l1: {
Expand All @@ -39,23 +58,7 @@ export function buildEboProcessor(
},
DEFAULT_MOCKED_PROTOCOL_CONTRACTS,
mockedPrivateKey,
);

const blockNumberRpcUrls = new Map<Caip2ChainId, string[]>([
["eip155:1" as Caip2ChainId, ["http://localhost:8539"]],
]);
const blockNumberService = new BlockNumberService(
blockNumberRpcUrls,
{
baseUrl: new URL("http://localhost"),
bearerToken: "secret-token",
bearerTokenExpirationWindow: 10,
servicePaths: {
block: "/block",
blockByTime: "/blockbytime",
},
},
logger,
blockNumberService,
);

const actorsManager = new EboActorsManager();
Expand Down
Loading