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

test: e2e dispute #72

Merged
merged 22 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8cd31c2
docs: add error types for ProphetCodec functions
0xyaco Oct 22, 2024
65ff4c3
chore: fix linters
0xyaco Oct 22, 2024
30857c1
fix: handle chains with blocks with same timestamp
0xyaco Oct 22, 2024
23ec54e
fix: add BigNumber to binary search
0xyaco Oct 23, 2024
e7d8b23
docs: add error types for ProphetCodec functions
0xyaco Oct 22, 2024
f34d525
fix: structs abi fields definition
0xyaco Oct 22, 2024
8cbcbcc
fix: avoid duplicating events during getEvents
0xyaco Oct 23, 2024
73c6351
fix: skip past events trying to be enqueued
0xyaco Oct 23, 2024
8b74a67
fix: handle request already created error appropriately
0xyaco Oct 23, 2024
1f47682
test: happy path working
0xyaco Oct 23, 2024
7885d9d
chore: remove caret from package.json
0xyaco Oct 23, 2024
0d0ba6b
Merge branch 'dev' into fix/blocknumber-binsearch
0xyaco Oct 23, 2024
b494c94
fix: candidate block number maths
0xyaco Oct 24, 2024
d1e2c55
refactor: normalize search methods naming
0xyaco Oct 24, 2024
4e9c335
Merge branch 'fix/blocknumber-binsearch' into fix/e2e-scenario-1
0xyaco Oct 24, 2024
635ac60
fix: fix blocks interval bounds during events sync
0xyaco Oct 24, 2024
86fb47c
test: test E2E response disputal
0xyaco Oct 24, 2024
c8b7399
fix: fix logging and comment
0xyaco Oct 25, 2024
e711311
fix: wait for disputestatus event
0xyaco Oct 25, 2024
d3ba273
Merge remote-tracking branch 'origin/dev' into test/e2e-scenario-2
0xyaco Oct 25, 2024
913649c
docs: finalize request docs
0xyaco Oct 25, 2024
a1b0fe6
fix: use Promise.all during pledging for dispute
0xyaco Oct 25, 2024
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
389 changes: 367 additions & 22 deletions apps/agent/test/e2e/scenarios/01_happy_path/index.spec.ts

Large diffs are not rendered by default.

27 changes: 18 additions & 9 deletions apps/agent/test/e2e/utils/prophet-e2e-scaffold/eboCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
createTestClient,
createWalletClient,
encodeFunctionData,
formatEther,
http,
HttpTransport,
parseAbi,
Expand Down Expand Up @@ -226,8 +227,8 @@ interface SetUpProphetInput {
accounts: Account[];
/** Map of deployed contracts */
deployedContracts: DeployContractsOutput;
/** Bond amount */
bondAmount: bigint;
/** GRT amount to provision account with to be able to bond tokens throughout its operation */
grtProvisionAmount: bigint;
/** Arbitrator address to use to add chains into EBORequestCreator */
arbitratorAddress: Address;
/** GRT address */
Expand All @@ -244,7 +245,13 @@ interface SetUpProphetInput {
* @param input {@link SetUpProphetInput}
*/
export async function setUpProphet(input: SetUpProphetInput) {
const { chainsToAdd, accounts, deployedContracts, anvilClient, bondAmount } = input;
const {
chainsToAdd,
accounts,
deployedContracts,
anvilClient,
grtProvisionAmount: bondAmount,
} = input;
const { arbitratorAddress, grtAddress, horizonStakingAddress } = input;

await approveEboProphetModules(accounts, deployedContracts, anvilClient);
Expand Down Expand Up @@ -328,7 +335,7 @@ async function stakeGrtWithProvision(
horizonStaking: Address;
horizonAccountingExtension: Address;
},
bondSize: bigint,
grtProvisionAmount: bigint,
anvilClient: AnvilClient<HttpTransport, Chain, undefined>,
) {
console.log("Staking GRT into Horizon...");
Expand All @@ -343,30 +350,32 @@ async function stakeGrtWithProvision(
to: grt,
data: encodeFunctionData({
abi: parseAbi(["function approve(address, uint256)"]),
args: [horizonStaking, bondSize * 5n],
args: [horizonStaking, grtProvisionAmount],
}),
});

await anvilClient.waitForTransactionReceipt({
hash: approveHash,
});

console.log(`Staking for ${account.address} ${bondSize}...`);
console.log(`Staking for ${account.address} ${formatEther(grtProvisionAmount)} GRT...`);

const stakeHash = await anvilClient.sendTransaction({
account: account,
to: horizonStaking,
data: encodeFunctionData({
abi: parseAbi(["function stake(uint256)"]),
args: [bondSize],
args: [grtProvisionAmount],
}),
});

await anvilClient.waitForTransactionReceipt({
hash: stakeHash,
});

console.log(`Provisioning ${bondSize} for ${account.address}...`);
console.log(
`Provisioning ${account.address} with ${formatEther(grtProvisionAmount)} GRT...`,
);

const provisionHash = await anvilClient.sendTransaction({
account: account,
Expand All @@ -376,7 +385,7 @@ async function stakeGrtWithProvision(
args: [
account.address,
horizonAccountingExtension,
bondSize,
grtProvisionAmount,
// TODO: use contract call to get this value
// https://github.com/defi-wonderland/EBO-core/blob/175bcd57c3254a90dd6fcbf53b3db3359085551f/src/contracts/HorizonAccountingExtension.sol#L38C26-L38C42
1_000_000,
Expand Down
61 changes: 61 additions & 0 deletions apps/agent/test/e2e/utils/prophet-e2e-scaffold/epochManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { epochManagerAbi } from "@ebo-agent/automated-dispute";
import { Address, Chain, HttpTransport } from "viem";

import { AnvilClient } from "./anvil";

type SetEpochLengthInput = {
client: AnvilClient<HttpTransport, Chain>;
governorAddress: Address;
epochManagerAddress: Address;
length: bigint;
};

export const setEpochLength = async (params: SetEpochLengthInput) => {
const { client, governorAddress, epochManagerAddress, length } = params;

client.impersonateAccount({
address: governorAddress,
});

const tx = await client.writeContract({
address: epochManagerAddress,
account: governorAddress,
abi: epochManagerAbi,
functionName: "setEpochLength",
args: [length],
});

await client.waitForTransactionReceipt({ hash: tx });

client.stopImpersonatingAccount({
address: governorAddress,
});
};

type GetEpochLengthInput = Omit<SetEpochLengthInput, "length">;

export const getEpochLength = async (params: GetEpochLengthInput) => {
const { client, governorAddress, epochManagerAddress } = params;

return await client.readContract({
address: epochManagerAddress,
account: governorAddress,
abi: epochManagerAbi,
functionName: "epochLength",
});
};

type GetCurrentEpochInput = {
client: AnvilClient<HttpTransport, Chain>;
epochManagerAddress: Address;
};

export const getCurrentEpoch = async (params: GetCurrentEpochInput) => {
const { client, epochManagerAddress } = params;

return await client.readContract({
address: epochManagerAddress,
abi: epochManagerAbi,
functionName: "currentEpoch",
});
};
16 changes: 10 additions & 6 deletions apps/agent/test/e2e/utils/prophet-e2e-scaffold/waitForEvent.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { AbiEvent, GetLogsParameters, Log } from "viem";
import { AbiEvent, GetLogsParameters, Log, MaybeAbiEventName } from "viem";

import { AnvilClient } from "./anvil.js";

interface WaitForEventInput<abi extends AbiEvent, client extends AnvilClient> {
/** Client to use for event polling */
client: client;
/** Event filtering */
filter: GetLogsParameters<abi, never, true>;
filter: GetLogsParameters<abi, [abi], true>;
/** Matcher to apply to filtered events */
matcher: (log: Log<bigint, number, boolean, abi, true>) => boolean;
matcher?: (
log: Log<bigint, number, false, abi, true, [abi], MaybeAbiEventName<abi>>,
) => boolean;

/** Event polling interval in milliseconds */
pollingIntervalMs: number;
/** Block number to time out after the polled chain has reached the specified block */
Expand All @@ -31,12 +34,13 @@ export async function waitForEvent<abi extends AbiEvent, client extends AnvilCli
do {
currentBlock = (await client.getBlock({ blockTag: "latest" })).number;

const logs = await client.getLogs<abi, never, true>(filter);
const logs = await client.getLogs<abi, [abi], true>(filter);
const matchingLogs = matcher ? logs.filter(matcher) : logs;

if (logs.some(matcher)) return true;
if (matchingLogs && matchingLogs.length > 0) return matchingLogs[0];

await new Promise((r) => setTimeout(r, pollingInterval));
} while (currentBlock < blockTimeout);

return false;
throw new Error(`Event ${filter.event?.name} not found.`);
}
1 change: 1 addition & 0 deletions apps/scripts/test/approveAccountingModules.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ describe("approveModules script", () => {
"Approved module: Bonded Response Module at address 0xBondedResponseModule",
),
);

expect(console.log).toHaveBeenCalledWith(
expect.stringContaining(
"Approved module: Bond Escalation Module at address 0xBondEscalationModule",
Expand Down
4 changes: 2 additions & 2 deletions packages/automated-dispute/src/exceptions/errorFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,15 +283,15 @@ const errorStrategiesEntries: [ErrorName, ErrorHandlingStrategy][] = [
{
shouldNotify: false,
shouldTerminate: false,
shouldReenqueue: true,
shouldReenqueue: false,
},
],
[
"BondEscalationModule_DisputeWindowOver",
{
shouldNotify: false,
shouldTerminate: false,
shouldReenqueue: true,
shouldReenqueue: false,
},
],
[
Expand Down
2 changes: 2 additions & 0 deletions packages/automated-dispute/src/exceptions/errorHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export class ErrorHandler {

if (strategy.shouldTerminate && context.terminateActor) {
context.terminateActor();
} else {
this.logger.warn(`Event handling caused an error`);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion packages/automated-dispute/src/external.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { EboProcessor, EboActorsManager, DiscordNotifier } from "./services/index.js";
export { EboProcessor, EboActorsManager, DiscordNotifier, ProphetCodec } from "./services/index.js";
export type { NotificationService } from "./interfaces/index.js";
export { ProtocolProvider } from "./providers/index.js";
export type { AccountingModules } from "./types/index.js";
export { oracleAbi, epochManagerAbi } from "./abis/index.js";
Loading