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: update RPC abis and behavior #94

Merged
merged 16 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
719 changes: 117 additions & 602 deletions packages/automated-dispute/src/abis/eboRequestCreator.ts

Large diffs are not rendered by default.

1,937 changes: 523 additions & 1,414 deletions packages/automated-dispute/src/abis/oracle.ts

Large diffs are not rendered by default.

24 changes: 22 additions & 2 deletions packages/automated-dispute/src/interfaces/protocolProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Caip2ChainId } from "@ebo-agent/shared";
import { Address, Block } from "viem";

import type {
AccessControl,
BondEscalation,
Dispute,
EboEvent,
Expand All @@ -13,7 +14,14 @@ import type {
} from "../types/index.js";
import { ProtocolContractsNames } from "../constants.js";

/**
* Represents the names of protocol contracts.
*/
export type ProtocolContract = (typeof ProtocolContractsNames)[number];

/**
* Maps protocol contract names to their respective addresses.
*/
export type ProtocolContractsAddresses = Record<ProtocolContract, Address>;

/**
Expand Down Expand Up @@ -93,26 +101,31 @@ export interface IWriteProvider {
*
* @param request The request data.
* @param response The response data.
* @param accessControl The access control parameters for proposing the response.
* @returns A promise that resolves when the response is proposed.
*/
proposeResponse(
request: Request["prophetData"],
response: Response["prophetData"],
accessControl: AccessControl,
): Promise<void>;

/**
* Disputes a proposed response.
*
* @param request The request data.
* @param request The request data.
* @param response The response data.
* @param dispute The dispute data.
* @param accessControl The access control parameters for disputing the response.
* @returns A promise that resolves when the response is disputed.
*/
disputeResponse(
request: Request["prophetData"],
response: Response["prophetData"],
dispute: Dispute["prophetData"],
accessControl: AccessControl,
): Promise<void>;

/**
* Pledges support for a dispute.
*
Expand Down Expand Up @@ -157,22 +170,29 @@ export interface IWriteProvider {
* @param request The request data.
* @param response The response data.
* @param dispute The dispute data.
* @param accessControl The access control parameters for escalating the dispute.
* @returns A promise that resolves when the dispute is escalated.
*/
escalateDispute(
request: Request["prophetData"],
response: Response["prophetData"],
dispute: Dispute["prophetData"],
accessControl: AccessControl,
): Promise<void>;

/**
* Finalizes a request after the response and dispute resolution are complete.
*
* @param request The request data.
* @param response The response data.
* @param accessControl The access control parameters for finalizing the request.
* @returns A promise that resolves when the request is finalized.
*/
finalize(request: Request["prophetData"], response: Response["prophetData"]): Promise<void>;
finalize(
request: Request["prophetData"],
response: Response["prophetData"],
accessControl: AccessControl,
): Promise<void>;

/**
* Approves a module in the accounting extension contract.
Expand Down
53 changes: 34 additions & 19 deletions packages/automated-dispute/src/providers/protocolProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import {
ProtocolContractsAddresses,
} from "../interfaces/index.js";
import { ProphetCodec } from "../services/index.js";
import { AccessControl } from "../types/index.js";

type RpcConfig = {
chainId: Caip2ChainId;
Expand Down Expand Up @@ -176,7 +177,11 @@ export class ProtocolProvider implements IProtocolProvider {
public: this.l2ReadClient,
wallet: this.l2WriteClient,
},
});
}) as GetContractReturnType<
typeof bondEscalationModuleAbi,
typeof this.l2WriteClient,
Address
>;

this.horizonAccountingExtensionContract = getContract({
address: contracts.horizonAccountingExtension,
Expand All @@ -185,7 +190,11 @@ export class ProtocolProvider implements IProtocolProvider {
public: this.l2ReadClient,
wallet: this.l2WriteClient,
},
});
}) as GetContractReturnType<
typeof horizonAccountingExtensionAbi,
typeof this.l2WriteClient,
Address
>;
}

public write: IWriteProvider = {
Expand Down Expand Up @@ -260,11 +269,11 @@ export class ProtocolProvider implements IProtocolProvider {
* The logging captures and logs the cloned `Request` and `Response` objects,
* ensuring the original objects remain unaltered.
*
*
* @param {string} url - The base URL for the HTTP transport.
* @param {number} timeout - The timeout duration in milliseconds for each HTTP request.
* @param {number} retryInterval - The delay in milliseconds before retrying a failed request.
* @returns {HttpTransport} The configured HTTP transport with logging enabled.
*
*/
private createHttpTransportWithLogging(
url: string,
Expand Down Expand Up @@ -617,7 +626,7 @@ export class ProtocolProvider implements IProtocolProvider {

const eventsWithTimestamps = await Promise.all(
events.map(async (event) => {
const { _requestId, _responseId, _caller } = event.args;
const { _requestId, _responseId } = event.args;

const timestamp = await this.getEventTimestamp(event);

Expand All @@ -632,7 +641,6 @@ export class ProtocolProvider implements IProtocolProvider {
metadata: {
requestId: HexUtils.normalize(_requestId) as RequestId,
responseId: HexUtils.normalize(_responseId) as ResponseId,
caller: _caller as Address,
blockNumber: event.blockNumber,
},
} as EboEvent<"OracleRequestFinalized">;
Expand All @@ -649,7 +657,7 @@ export class ProtocolProvider implements IProtocolProvider {
* @param {bigint} toBlock - The ending block number to fetch events up to.
* @returns {Promise<EboEvent<EboEventName>[]>} A promise that resolves to an array of Oracle events.
*/
async getOracleEvents(fromBlock: bigint, toBlock: bigint) {
async getOracleEvents(fromBlock: bigint, toBlock: bigint): Promise<EboEvent<EboEventName>[]> {
const [
requestCreatedEvents,
responseProposedEvents,
Expand Down Expand Up @@ -744,7 +752,7 @@ export class ProtocolProvider implements IProtocolProvider {
* @returns A promise that resolves to an array of EboEvents sorted by block number and log index.
* @throws {Error} If the block range is invalid or if there's an error fetching events.
*/
async getEvents(fromBlock: bigint, toBlock: bigint) {
async getEvents(fromBlock: bigint, toBlock: bigint): Promise<EboEvent<EboEventName>[]> {
if (fromBlock > toBlock) {
throw new InvalidBlockRangeError(fromBlock, toBlock);
}
Expand All @@ -761,7 +769,7 @@ export class ProtocolProvider implements IProtocolProvider {
* @param {EboEvent<EboEventName>[][]} streams - A collection of EboEvent[] arrays.
* @returns {EboEvent<EboEventName>[]} The merged and sorted event array.
*/
private mergeEventStreams(...streams: EboEvent<EboEventName>[][]) {
private mergeEventStreams(...streams: EboEvent<EboEventName>[][]): EboEvent<EboEventName>[] {
return streams
.reduce((acc, curr) => acc.concat(curr), [])
.sort((a, b) => {
Expand Down Expand Up @@ -841,7 +849,7 @@ export class ProtocolProvider implements IProtocolProvider {
* @param {Address} user - The address of the user. If not specified, it fallbacks to the L2 account address.
* @returns {Promise<Address[]>} A promise that resolves with an array of approved modules for the user.
*/
async getApprovedModules(user?: Address): Promise<readonly Address[]> {
async getApprovedModules(user: Address): Promise<readonly Address[]> {
const bondAddress = user ?? this.getAccountAddress();

const modules = await this.horizonAccountingExtensionContract.read.approvedModules([
Expand All @@ -857,20 +865,20 @@ export class ProtocolProvider implements IProtocolProvider {
* and then executing it if the simulation is successful.
*
* @param {bigint} epoch - The epoch for which the request is being created.
* @param {Caip2ChainId} chain - A chain identifier for which the request should be created.
* @param {Caip2ChainId} chain - An array of chain identifiers for which the request should be created.
* @throws {Error} Throws an error if the chains array is empty or if the transaction fails.
* @returns {Promise<void>} A promise that resolves when the request is successfully created.
*/
async createRequest(epoch: bigint, chain: Caip2ChainId): Promise<void> {
const { request } = await this.l2ReadClient.simulateContract({
async createRequest(epoch: bigint, chains: Caip2ChainId): Promise<void> {
const { request: simulatedRequest } = await this.l2ReadClient.simulateContract({
address: this.eboRequestCreatorContract.address,
abi: eboRequestCreatorAbi,
functionName: "createRequest",
args: [epoch, chain],
args: [epoch, chains],
account: this.l2WriteClient.account,
});

const hash = await this.l2WriteClient.writeContract(request);
const hash = await this.l2WriteClient.writeContract(simulatedRequest);

const { transactionReceiptConfirmations } = this.rpcConfig.l2;
const receipt = await this.l2ReadClient.waitForTransactionReceipt({
Expand All @@ -888,19 +896,21 @@ export class ProtocolProvider implements IProtocolProvider {
*
* @param {Request["prophetData"]} request - The request data.
* @param {Response["prophetData"]} response - The response data to propose.
* @param {AccessControl} accessControl - The access control parameters for proposing the response.
* @throws {TransactionExecutionError} Throws if the transaction fails during execution.
* @throws {ContractFunctionRevertedError} Throws if the contract function reverts.
* @returns {Promise<void>}
*/
async proposeResponse(
request: Request["prophetData"],
response: Response["prophetData"],
accessControl: AccessControl,
): Promise<void> {
const { request: simulatedRequest } = await this.l2ReadClient.simulateContract({
address: this.oracleContract.address,
abi: oracleAbi,
functionName: "proposeResponse",
args: [request, response],
args: [request, response, accessControl],
account: this.l2WriteClient.account,
});

Expand All @@ -923,6 +933,7 @@ export class ProtocolProvider implements IProtocolProvider {
* @param {Request["prophetData"]} request - The request data.
* @param {Response["prophetData"]} response - The response data to dispute.
* @param {Dispute["prophetData"]} dispute - The dispute data.
* @param {AccessControl} accessControl - The access control parameters for disputing the response.
* @throws {TransactionExecutionError} Throws if the transaction fails during execution.
* @throws {ContractFunctionRevertedError} Throws if the contract function reverts.
* @returns {Promise<void>}
Expand All @@ -931,12 +942,13 @@ export class ProtocolProvider implements IProtocolProvider {
request: Request["prophetData"],
response: Response["prophetData"],
dispute: Dispute["prophetData"],
accessControl: AccessControl,
): Promise<void> {
const { request: simulatedRequest } = await this.l2ReadClient.simulateContract({
address: this.oracleContract.address,
abi: oracleAbi,
functionName: "disputeResponse",
args: [request, response, dispute],
args: [request, response, dispute, accessControl],
account: this.l2WriteClient.account,
});

Expand Down Expand Up @@ -1112,6 +1124,7 @@ export class ProtocolProvider implements IProtocolProvider {
* @param {Request["prophetData"]} request - The request data.
* @param {Response["prophetData"]} response - The response data.
* @param {Dispute["prophetData"]} dispute - The dispute data.
* @param {AccessControl} accessControl - The access control parameters for escalating the dispute.
* @throws {TransactionExecutionError} Throws if the transaction fails during execution.
* @throws {ContractFunctionRevertedError} Throws if the contract function reverts.
* @returns {Promise<void>}
Expand All @@ -1120,12 +1133,13 @@ export class ProtocolProvider implements IProtocolProvider {
request: Request["prophetData"],
response: Response["prophetData"],
dispute: Dispute["prophetData"],
accessControl: AccessControl,
): Promise<void> {
const { request: simulatedRequest } = await this.l2ReadClient.simulateContract({
address: this.oracleContract.address,
abi: oracleAbi,
functionName: "escalateDispute",
args: [request, response, dispute],
args: [request, response, dispute, accessControl],
account: this.l2WriteClient.account,
});

Expand All @@ -1152,20 +1166,21 @@ export class ProtocolProvider implements IProtocolProvider {
*
* @param {Request["prophetData"]} request - The request data.
* @param {Response["prophetData"]} response - The response data to finalize.
* @param {AccessControl} accessControl - The access control parameters for finalizing the request.
* @throws {TransactionExecutionError} Throws if the transaction fails during execution.
* @throws {ContractFunctionRevertedError} Throws if the contract function reverts.
* @returns {Promise<void>}
*/

async finalize(
request: Request["prophetData"],
response: Response["prophetData"],
accessControl: AccessControl,
): Promise<void> {
const { request: simulatedRequest } = await this.l2ReadClient.simulateContract({
address: this.oracleContract.address,
abi: oracleAbi,
functionName: "finalize",
args: [request, response],
args: [request, response, accessControl],
account: this.l2WriteClient.account,
});

Expand Down
33 changes: 29 additions & 4 deletions packages/automated-dispute/src/services/eboActor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import {
ProphetCodec,
UpdateDisputeStatus,
} from "../services/index.js";
import { ActorRequest } from "../types/index.js";
import { AccessControl, ActorRequest } from "../types/index.js";

/**
* Compare function to sort events chronologically in ascending order by block number
Expand Down Expand Up @@ -112,6 +112,17 @@ export class EboActor {
this.errorHandler = new ErrorHandler(this.notificationService, this.logger);
}

/**
* Get the default access control object.
* @returns AccessControl object
*/
private getDefaultAccessControl(): AccessControl {
return {
user: this.protocolProvider.getAccountAddress(),
data: "0x",
Copy link
Collaborator

Choose a reason for hiding this comment

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

The 0x is excellent, no need to add anything else to the data field

};
}

/**
* Enqueue events to be processed by the actor.
*
Expand Down Expand Up @@ -362,7 +373,11 @@ export class EboActor {
};

try {
await this.protocolProvider.finalize(request.prophetData, nullResponseProphetData);
await this.protocolProvider.finalize(
request.prophetData,
nullResponseProphetData,
this.getDefaultAccessControl(),
);
this.logger.info(`Request ${request.id} finalized with no response.`, {
requestId: request.id,
});
Expand Down Expand Up @@ -505,7 +520,11 @@ export class EboActor {
});

try {
await this.protocolProvider.finalize(request.prophetData, response.prophetData);
await this.protocolProvider.finalize(
request.prophetData,
response.prophetData,
this.getDefaultAccessControl(),
);
} catch (err) {
if (err instanceof CustomContractError) {
this.logger.warn(`Finalizing request reverted: ${err.name}`, {
Expand Down Expand Up @@ -584,6 +603,7 @@ export class EboActor {
request.prophetData,
response.prophetData,
dispute.prophetData,
this.getDefaultAccessControl(),
);

this.logger.info(`Dispute ${dispute.id} escalated.`, { disputeId: dispute.id });
Expand Down Expand Up @@ -810,7 +830,11 @@ export class EboActor {
};

try {
await this.protocolProvider.proposeResponse(request.prophetData, response);
await this.protocolProvider.proposeResponse(
request.prophetData,
response,
this.getDefaultAccessControl(),
);

this.logger.info(`Block ${responseBody.block} proposed`, {
blockNumber: responseBody.block,
Expand Down Expand Up @@ -886,6 +910,7 @@ export class EboActor {
request.prophetData,
proposedResponse.prophetData,
dispute,
this.getDefaultAccessControl(),
);
} catch (err) {
if (err instanceof ContractFunctionRevertedError) {
Expand Down
3 changes: 2 additions & 1 deletion packages/automated-dispute/src/services/eboProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ export class EboProcessor {
* @throws {PendingModulesApproval} when there is at least one module pending approval
*/
private async checkAllModulesApproved() {
const userAddress: Address = this.protocolProvider.getAccountAddress();
const approvedModules: readonly Address[] =
await this.protocolProvider.getApprovedModules();
await this.protocolProvider.getApprovedModules(userAddress);

const summary: Record<"approved" | "notApproved", Partial<AccountingModules>> = {
approved: {},
Expand Down
Loading