-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Feat(validator)/claimer #417
base: dev
Are you sure you want to change the base?
Changes from all commits
4e39a03
e6b5d7e
829bd77
fc5020c
e367173
c488c4a
a91a9c6
4ef27a7
4c7d59a
89b6b0b
cffaa00
9a7cc65
025345e
3a2ff60
f7ec86f
7b9ffa0
cd47f5f
6e34daa
d66c455
e4c617f
c54c899
f47ec8a
b2bf8d8
13d6e2b
979394b
de4b1b6
ee90f37
c3d2a23
4aa595a
28e6095
23937af
c9dbe57
30b174d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,20 @@ | ||
PRIVATE_KEY= | ||
|
||
# Devnet RPCs | ||
RPC_CHIADO=https://rpc.chiadochain.net | ||
RPC_ARB_SEPOLIA=https://sepolia-rollup.arbitrum.io/rpc | ||
RPC_SEPOLIA= | ||
# Networks: devnet, testnet, mainnet | ||
NETWORKS=devnet,testnet | ||
|
||
# Testnet or Mainnet RPCs | ||
|
||
# RPCs | ||
RPC_ARB=https://sepolia-rollup.arbitrum.io/rpc | ||
RPC_ETH= | ||
RPC_GNOSIS=https://rpc.chiadochain.net | ||
|
||
# Testnet or Mainnet Addresses | ||
# VEA Arbitrum to Ethereum | ||
VEAINBOX_ARB_TO_ETH_ADDRESS=0xE12daFE59Bc3A996362d54b37DFd2BA9279cAd06 | ||
VEAOUTBOX_ARB_TO_ETH_ADDRESS=0x209BFdC6B7c66b63A8382196Ba3d06619d0F12c9 | ||
# VEA Arbitrum to GNOSIS | ||
VEAINBOX_ARB_TO_GNOSIS_ADDRESS=0x854374483572FFcD4d0225290346279d0718240b | ||
VEAOUTBOX_ARB_TO_GNOSIS_ADDRESS=0x2f1788F7B74e01c4C85578748290467A5f063B0b | ||
VEAROUTER_ARB_TO_GNOSIS_ADDRESS=0x5BE03fDE7794Bc188416ba16932510Ed1277b193 | ||
GNOSIS_AMB_ADDRESS=0x8448E15d0e706C0298dECA99F0b4744030e59d7d | ||
|
||
VEAOUTBOX_CHAIN_ID=421611 | ||
GNOSIS_AMB_ADDRESS=0x8448E15d0e706C0298dECA99F0b4744030e59d7d | ||
|
||
# Devnet Addresses | ||
VEAINBOX_ARBSEPOLIA_TO_SEPOLIA_ADDRESS=0x906dE43dBef27639b1688Ac46532a16dc07Ce410 | ||
VEAOUTBOX_ARBSEPOLIA_TO_SEPOLIA_ADDRESS=0x906dE43dBef27639b1688Ac46532a16dc07Ce410 | ||
VEAOUTBOX_CHAINS=11155111,421611 | ||
|
||
# vescan subgraph endpoints | ||
VEAINBOX_SUBGRAPH=https://api.studio.thegraph.com/query/user/inbox-arb-sep/version/latest | ||
VEAOUTBOX_SUBGRAPH=https://api.studio.thegraph.com/query/user/outbox-arb-sep/version/latest | ||
|
||
TRANSACTION_BATCHER_CONTRACT_ADDRESS_SEPOLIA=0xe7953da7751063d0a41ba727c32c762d3523ade8 | ||
TRANSACTION_BATCHER_CONTRACT_ADDRESS_CHIADO=0xcC0a08D4BCC5f91ee9a1587608f7a2975EA75d73 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,10 +22,8 @@ | |
"@kleros/vea-contracts": "workspace:^", | ||
"@typechain/ethers-v6": "^0.5.1", | ||
"dotenv": "^16.4.5", | ||
"pm2": "^5.2.2", | ||
"typescript": "^4.9.5", | ||
"web3": "^4.16.0", | ||
"web3-batched-send": "^1.0.3" | ||
"pm2": "^6.0.5", | ||
"typescript": "^4.9.5" | ||
Comment on lines
+25
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainUpdated PM2 and removed Web3 dependencies
🏁 Script executed: #!/bin/bash
# Check for any remaining web3 imports in the codebase that might break after removing these dependencies
rg -i "require\(['\"]web3['\"]" --type ts
rg -i "import.*from ['\"]web3['\"]" --type ts
rg -i "web3-batched-send" --type ts Length of output: 277 Action Required: Remove Remaining Web3 References The changes in
Please update or remove these imports to ensure consistency with the dependency removals and to prevent potential runtime issues. |
||
}, | ||
"devDependencies": { | ||
"@types/jest": "^29.5.14", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
import { ethers } from "ethers"; | ||
import { checkAndClaim, CheckAndClaimParams } from "./claimer"; | ||
import { ClaimHonestState } from "../utils/claim"; | ||
import { Network } from "../consts/bridgeRoutes"; | ||
|
||
describe("claimer", () => { | ||
const NETWORK = Network.DEVNET; | ||
let veaOutbox: any; | ||
let veaInbox: any; | ||
let veaInboxProvider: any; | ||
let veaOutboxProvider: any; | ||
let emitter: any; | ||
let mockClaim: any; | ||
let mockGetLatestClaimedEpoch: any; | ||
let mockGetTransactionHandler: any; | ||
let mockDeps: CheckAndClaimParams; | ||
|
||
let mockTransactionHandler: any; | ||
const mockTransactions = { | ||
claimTxn: "0x111", | ||
withdrawClaimDepositTxn: "0x222", | ||
startVerificationTxn: "0x333", | ||
verifySnapshotTxn: "0x444", | ||
devnetAdvanceStateTxn: "0x555", | ||
}; | ||
beforeEach(() => { | ||
mockClaim = { | ||
stateRoot: "0x1234", | ||
claimer: "0xFa00D29d378EDC57AA1006946F0fc6230a5E3288", | ||
timestampClaimed: 1234, | ||
timestampVerification: 0, | ||
blocknumberVerification: 0, | ||
honest: 0, | ||
challenger: ethers.ZeroAddress, | ||
}; | ||
veaInbox = { | ||
snapshots: jest.fn().mockResolvedValue(mockClaim.stateRoot), | ||
}; | ||
|
||
veaOutbox = { | ||
stateRoot: jest.fn().mockResolvedValue(mockClaim.stateRoot), | ||
}; | ||
veaOutboxProvider = { | ||
getBlock: jest.fn().mockResolvedValue({ number: 0, timestamp: 110 }), | ||
}; | ||
emitter = { | ||
emit: jest.fn(), | ||
}; | ||
|
||
mockGetLatestClaimedEpoch = jest.fn(); | ||
mockGetTransactionHandler = jest.fn().mockReturnValue(function DummyTransactionHandler(params: any) { | ||
// Return an object that matches our expected transaction handler. | ||
return mockTransactionHandler; | ||
}); | ||
mockDeps = { | ||
chainId: 0, | ||
claim: mockClaim, | ||
network: NETWORK, | ||
epoch: 10, | ||
epochPeriod: 10, | ||
veaInbox, | ||
veaInboxProvider, | ||
veaOutboxProvider, | ||
veaOutbox, | ||
transactionHandler: null, | ||
emitter, | ||
fetchLatestClaimedEpoch: mockGetLatestClaimedEpoch, | ||
now: 110000, // (epoch+ 1) * epochPeriod * 1000 for claimable epoch | ||
}; | ||
|
||
mockTransactionHandler = { | ||
withdrawClaimDeposit: jest.fn().mockImplementation(() => { | ||
mockTransactionHandler.transactions.withdrawClaimDepositTxn = mockTransactions.withdrawClaimDepositTxn; | ||
return Promise.resolve(); | ||
}), | ||
makeClaim: jest.fn().mockImplementation(() => { | ||
mockTransactionHandler.transactions.claimTxn = mockTransactions.claimTxn; | ||
return Promise.resolve(); | ||
}), | ||
startVerification: jest.fn().mockImplementation(() => { | ||
mockTransactionHandler.transactions.startVerificationTxn = mockTransactions.startVerificationTxn; | ||
return Promise.resolve(); | ||
}), | ||
verifySnapshot: jest.fn().mockImplementation(() => { | ||
mockTransactionHandler.transactions.verifySnapshotTxn = mockTransactions.verifySnapshotTxn; | ||
return Promise.resolve(); | ||
}), | ||
transactions: { | ||
claimTxn: "0x0", | ||
withdrawClaimDepositTxn: "0x0", | ||
startVerificationTxn: "0x0", | ||
verifySnapshotTxn: "0x0", | ||
}, | ||
}; | ||
}); | ||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
describe("checkAndClaim", () => { | ||
beforeEach(() => { | ||
mockTransactionHandler = { | ||
withdrawClaimDeposit: jest.fn().mockImplementation(() => { | ||
mockTransactionHandler.transactions.withdrawClaimDepositTxn = mockTransactions.withdrawClaimDepositTxn; | ||
return Promise.resolve(); | ||
}), | ||
makeClaim: jest.fn().mockImplementation(() => { | ||
mockTransactionHandler.transactions.claimTxn = mockTransactions.claimTxn; | ||
return Promise.resolve(); | ||
}), | ||
startVerification: jest.fn().mockImplementation(() => { | ||
mockTransactionHandler.transactions.startVerificationTxn = mockTransactions.startVerificationTxn; | ||
return Promise.resolve(); | ||
}), | ||
verifySnapshot: jest.fn().mockImplementation(() => { | ||
mockTransactionHandler.transactions.verifySnapshotTxn = mockTransactions.verifySnapshotTxn; | ||
return Promise.resolve(); | ||
}), | ||
devnetAdvanceState: jest.fn().mockImplementation(() => { | ||
mockTransactionHandler.transactions.devnetAdvanceStateTxn = mockTransactions.devnetAdvanceStateTxn; | ||
return Promise.resolve(); | ||
}), | ||
transactions: { | ||
claimTxn: "0x0", | ||
withdrawClaimDepositTxn: "0x0", | ||
startVerificationTxn: "0x0", | ||
verifySnapshotTxn: "0x0", | ||
}, | ||
}; | ||
mockGetTransactionHandler = jest.fn().mockReturnValue(function DummyTransactionHandler(param: any) { | ||
return mockTransactionHandler; | ||
}); | ||
mockDeps.fetchTransactionHandler = mockGetTransactionHandler; | ||
}); | ||
it("should return null if no claim is made for a passed epoch", async () => { | ||
mockDeps.epoch = 7; // claimable epoch - 3 | ||
mockDeps.claim = null; | ||
|
||
mockDeps.fetchTransactionHandler = mockGetTransactionHandler; | ||
const result = await checkAndClaim(mockDeps); | ||
expect(result).toBeNull(); | ||
}); | ||
it("should return null if no snapshot is saved on the inbox for a claimable epoch", async () => { | ||
veaInbox.snapshots = jest.fn().mockResolvedValue(ethers.ZeroHash); | ||
mockGetLatestClaimedEpoch = jest.fn().mockResolvedValue({ | ||
challenged: false, | ||
stateroot: "0x1111", | ||
}); | ||
mockDeps.claim = null; | ||
mockDeps.fetchLatestClaimedEpoch = mockGetLatestClaimedEpoch; | ||
const result = await checkAndClaim(mockDeps); | ||
expect(result).toBeNull(); | ||
}); | ||
it("should return null if there are no new messages in the inbox", async () => { | ||
veaInbox.snapshots = jest.fn().mockResolvedValue(mockClaim.stateRoot); | ||
mockGetLatestClaimedEpoch = jest.fn().mockResolvedValue({ | ||
challenged: false, | ||
stateroot: "0x1111", | ||
}); | ||
mockDeps.claim = null; | ||
mockDeps.fetchLatestClaimedEpoch = mockGetLatestClaimedEpoch; | ||
const result = await checkAndClaim(mockDeps); | ||
expect(result).toBeNull(); | ||
}); | ||
describe("devnet", () => { | ||
beforeEach(() => { | ||
mockDeps.network = Network.DEVNET; | ||
}); | ||
it("should make a valid claim and advance state", async () => { | ||
veaInbox.snapshots = jest.fn().mockResolvedValue("0x7890"); | ||
mockGetLatestClaimedEpoch = jest.fn().mockResolvedValue({ | ||
challenged: false, | ||
stateroot: mockClaim.stateRoot, | ||
}); | ||
mockDeps.transactionHandler = mockTransactionHandler; | ||
mockDeps.fetchLatestClaimedEpoch = mockGetLatestClaimedEpoch; | ||
mockDeps.claim = null; | ||
mockDeps.veaInbox = veaInbox; | ||
const result = await checkAndClaim(mockDeps); | ||
expect(result.transactions.devnetAdvanceStateTxn).toBe(mockTransactions.devnetAdvanceStateTxn); | ||
}); | ||
}); | ||
describe("testnet", () => { | ||
beforeEach(() => { | ||
mockDeps.network = Network.TESTNET; | ||
}); | ||
it("should make a valid claim if no claim is made", async () => { | ||
veaInbox.snapshots = jest.fn().mockResolvedValue("0x7890"); | ||
mockGetLatestClaimedEpoch = jest.fn().mockResolvedValue({ | ||
challenged: false, | ||
stateroot: mockClaim.stateRoot, | ||
}); | ||
mockDeps.transactionHandler = mockTransactionHandler; | ||
mockDeps.fetchLatestClaimedEpoch = mockGetLatestClaimedEpoch; | ||
mockDeps.claim = null; | ||
mockDeps.veaInbox = veaInbox; | ||
const result = await checkAndClaim(mockDeps); | ||
expect(result.transactions.claimTxn).toBe(mockTransactions.claimTxn); | ||
}); | ||
it("should make a valid claim if last claim was challenged", async () => { | ||
veaInbox.snapshots = jest.fn().mockResolvedValue(mockClaim.stateRoot); | ||
mockGetLatestClaimedEpoch = jest.fn().mockResolvedValue({ | ||
challenged: true, | ||
stateroot: mockClaim.stateRoot, | ||
}); | ||
mockDeps.transactionHandler = mockTransactionHandler; | ||
mockDeps.fetchLatestClaimedEpoch = mockGetLatestClaimedEpoch; | ||
mockDeps.claim = null; | ||
mockDeps.veaInbox = veaInbox; | ||
const result = await checkAndClaim(mockDeps); | ||
expect(result.transactions.claimTxn).toEqual(mockTransactions.claimTxn); | ||
}); | ||
it("should withdraw claim deposit if claimer is honest", async () => { | ||
mockDeps.transactionHandler = mockTransactionHandler; | ||
mockClaim.honest = ClaimHonestState.CLAIMER; | ||
const result = await checkAndClaim(mockDeps); | ||
expect(result.transactions.withdrawClaimDepositTxn).toEqual(mockTransactions.withdrawClaimDepositTxn); | ||
}); | ||
it("should start verification if verification is not started", async () => { | ||
mockDeps.transactionHandler = mockTransactionHandler; | ||
mockClaim.honest = ClaimHonestState.NONE; | ||
const result = await checkAndClaim(mockDeps); | ||
expect(result.transactions.startVerificationTxn).toEqual(mockTransactions.startVerificationTxn); | ||
}); | ||
it("should verify snapshot if verification is started", async () => { | ||
mockDeps.transactionHandler = mockTransactionHandler; | ||
mockClaim.honest = ClaimHonestState.NONE; | ||
mockClaim.timestampVerification = 1234; | ||
mockDeps.claim = mockClaim; | ||
const result = await checkAndClaim(mockDeps); | ||
expect(result.transactions.verifySnapshotTxn).toEqual(mockTransactions.verifySnapshotTxn); | ||
}); | ||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify mainnet inclusion in NETWORKS variable
Line 3 mentions "devnet, testnet, mainnet" as supported networks, but line 4 only includes "devnet,testnet". If mainnet support is planned but not yet implemented, consider adding a comment to clarify this intention.
🏁 Script executed:
Length of output: 4470
Clarify Mainnet Inclusion in .env.dist
The comment in the file lists the supported networks as "devnet, testnet, mainnet" but the NETWORKS variable only includes "devnet,testnet". Since multiple parts of the codebase (e.g., tests and configurations) reference mainnet, please either: