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(svm): relay root bundle event #683

Merged
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
7 changes: 7 additions & 0 deletions programs/svm-spoke/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ pub struct EnabledDepositRoute {
pub enabled: bool,
}

#[event]
pub struct RelayedRootBundle {
pub root_bundle_id: u32,
pub relayer_refund_root: [u8; 32],
pub slow_relay_root: [u8; 32],
}

// Deposit events
#[event]
pub struct V3FundsDeposited {
Expand Down
14 changes: 10 additions & 4 deletions programs/svm-spoke/src/instructions/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
constants::DISCRIMINATOR_SIZE,
constraints::is_local_or_remote_owner,
error::CustomError,
event::{EnabledDepositRoute, PausedDeposits, PausedFills, SetXDomainAdmin},
event::{EnabledDepositRoute, PausedDeposits, PausedFills, RelayedRootBundle, SetXDomainAdmin},
initialize_current_time,
state::{RootBundle, Route, State},
};
Expand Down Expand Up @@ -209,6 +209,7 @@ pub fn set_enable_route(
Ok(())
}

#[event_cpi]
#[derive(Accounts)]
pub struct RelayRootBundle<'info> {
#[account(
Expand Down Expand Up @@ -241,10 +242,15 @@ pub fn relay_root_bundle(
let root_bundle = &mut ctx.accounts.root_bundle;
root_bundle.relayer_refund_root = relayer_refund_root;
root_bundle.slow_relay_root = slow_relay_root;

emit_cpi!(RelayedRootBundle {
root_bundle_id: state.root_bundle_id,
relayer_refund_root,
slow_relay_root,
});

// Finally, increment the root bundle id
Copy link
Contributor

Choose a reason for hiding this comment

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

not directly related to this PR, but I think its confusing to have prop named root_bundle_id in state account. Instead it should be something to resemble number of relayed bundles or next_root_bundle_id - Maybe add this as TODO here

state.root_bundle_id += 1;

// TODO: add event
Ok(())
}

// TODO: add emergency_delete_root_bundle
10 changes: 5 additions & 5 deletions programs/svm-spoke/src/state/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ pub struct State {
pub owner: Pubkey,
pub seed: u64, // Add a seed to the state to enable multiple deployments.
pub number_of_deposits: u32,
pub chain_id: u64, // Across definition of chainId for Solana.
pub current_time: u32, // Only used in testable mode, else set to 0 on mainnet.
pub remote_domain: u32, // CCTP domain for Mainnet Ethereum.
pub cross_domain_admin: Pubkey, // HubPool on Mainnet Ethereum.
pub root_bundle_id: u32,
pub chain_id: u64, // Across definition of chainId for Solana.
pub current_time: u32, // Only used in testable mode, else set to 0 on mainnet.
pub remote_domain: u32, // CCTP domain for Mainnet Ethereum.
pub cross_domain_admin: Pubkey, // HubPool on Mainnet Ethereum.
pub root_bundle_id: u32, // TODO rename to next_root_bundle_id
pub deposit_quote_time_buffer: u32, // Deposit quote times can't be set more than this amount into the past/future.
pub fill_deadline_buffer: u32, // Fill deadlines can't be set more than this amount into the future.
}
61 changes: 48 additions & 13 deletions test/svm/SvmSpoke.Bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ describe("svm_spoke.bundle", () => {
const [rootBundle] = PublicKey.findProgramAddressSync(seeds, program.programId);

// Try to relay root bundle as non-owner
let relayRootBundleAccounts = { state: state, rootBundle, signer: nonOwner.publicKey };
let relayRootBundleAccounts = { state: state, rootBundle, signer: nonOwner.publicKey, program: program.programId };
try {
await program.methods
.relayRootBundle(relayerRefundRootArray, slowRelayRootArray)
Expand All @@ -114,7 +114,7 @@ describe("svm_spoke.bundle", () => {
}

// Relay root bundle as owner
relayRootBundleAccounts = { state, rootBundle, signer: owner };
relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
await program.methods
.relayRootBundle(relayerRefundRootArray, slowRelayRootArray)
.accounts(relayRootBundleAccounts)
Expand Down Expand Up @@ -146,7 +146,7 @@ describe("svm_spoke.bundle", () => {
const seeds2 = [Buffer.from("root_bundle"), state.toBuffer(), rootBundleIdBuffer2];
const [rootBundle2] = PublicKey.findProgramAddressSync(seeds2, program.programId);

relayRootBundleAccounts = { state, rootBundle: rootBundle2, signer: owner };
relayRootBundleAccounts = { state, rootBundle: rootBundle2, signer: owner, program: program.programId };
await program.methods
.relayRootBundle(relayerRefundRootArray2, slowRelayRootArray2)
.accounts(relayRootBundleAccounts)
Expand All @@ -155,6 +155,41 @@ describe("svm_spoke.bundle", () => {
stateAccountData = await program.account.state.fetch(state);
assert.isTrue(stateAccountData.rootBundleId.toString() === "2", "Root bundle index should be 2");
});

it("Tests Event Emission in Relay Root Bundle", async () => {
const relayerRefundRootBuffer = crypto.randomBytes(32);
const relayerRefundRootArray = Array.from(relayerRefundRootBuffer);
const slowRelayRootBuffer = crypto.randomBytes(32);
const slowRelayRootArray = Array.from(slowRelayRootBuffer);

let stateAccountData = await program.account.state.fetch(state);
const rootBundleId = stateAccountData.rootBundleId;
const rootBundleIdBuffer = Buffer.alloc(4);
rootBundleIdBuffer.writeUInt32LE(rootBundleId);
const seeds = [Buffer.from("root_bundle"), state.toBuffer(), rootBundleIdBuffer];
const [rootBundle] = PublicKey.findProgramAddressSync(seeds, program.programId);

// Relay root bundle as owner
const relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
const tx = await program.methods
.relayRootBundle(relayerRefundRootArray, slowRelayRootArray)
.accounts(relayRootBundleAccounts)
.rpc();

// Wait for event processing
await new Promise((resolve) => setTimeout(resolve, 1000));

// Check for the emitted event
const events = await readEvents(connection, tx, [program]);
const event = events.find((event) => event.name === "relayedRootBundle").data;
assert.isTrue(event.rootBundleId.toString() === rootBundleId.toString(), "Root bundle ID should match");
assert.isTrue(
event.relayerRefundRoot.toString() === relayerRefundRootArray.toString(),
"Relayer refund root should match"
);
assert.isTrue(event.slowRelayRoot.toString() === slowRelayRootArray.toString(), "Slow relay root should match");
});

it("Simple Leaf Refunds Relayers", async () => {
const relayerRefundLeaves: RelayerRefundLeafType[] = [];
const relayerARefund = new BN(400000);
Expand Down Expand Up @@ -185,7 +220,7 @@ describe("svm_spoke.bundle", () => {
const [rootBundle] = PublicKey.findProgramAddressSync(seeds, program.programId);

// Relay root bundle
let relayRootBundleAccounts = { state, rootBundle, signer: owner };
let relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
await program.methods.relayRootBundle(Array.from(root), Array.from(root)).accounts(relayRootBundleAccounts).rpc();

const remainingAccounts = [
Expand Down Expand Up @@ -316,7 +351,7 @@ describe("svm_spoke.bundle", () => {
const [rootBundle] = PublicKey.findProgramAddressSync(seeds, program.programId);

// Relay root bundle
let relayRootBundleAccounts = { state, rootBundle, signer: owner };
let relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
await program.methods.relayRootBundle(Array.from(root), Array.from(root)).accounts(relayRootBundleAccounts).rpc();

const remainingAccounts = [
Expand Down Expand Up @@ -457,7 +492,7 @@ describe("svm_spoke.bundle", () => {
const [rootBundle] = PublicKey.findProgramAddressSync(seeds, program.programId);

// Relay root bundle
let relayRootBundleAccounts = { state, rootBundle, signer: owner };
let relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
await program.methods.relayRootBundle(Array.from(root), Array.from(root)).accounts(relayRootBundleAccounts).rpc();

const remainingAccounts = [
Expand Down Expand Up @@ -519,7 +554,7 @@ describe("svm_spoke.bundle", () => {
const [rootBundle] = PublicKey.findProgramAddressSync(seeds, program.programId);

// Relay root bundle
let relayRootBundleAccounts = { state, rootBundle, signer: owner };
let relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
await program.methods.relayRootBundle(Array.from(root), Array.from(root)).accounts(relayRootBundleAccounts).rpc();

const remainingAccounts = [
Expand Down Expand Up @@ -581,7 +616,7 @@ describe("svm_spoke.bundle", () => {
const [rootBundle] = PublicKey.findProgramAddressSync(seeds, program.programId);

// Relay root bundle
let relayRootBundleAccounts = { state, rootBundle, signer: owner };
let relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
await program.methods.relayRootBundle(Array.from(root), Array.from(root)).accounts(relayRootBundleAccounts).rpc();

const remainingAccounts = [{ pubkey: relayerTA, isWritable: true, isSigner: false }];
Expand Down Expand Up @@ -741,7 +776,7 @@ describe("svm_spoke.bundle", () => {
const [rootBundle] = PublicKey.findProgramAddressSync(seeds, program.programId);

// Relay root bundle
const relayRootBundleAccounts = { state, rootBundle, signer: owner };
const relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
await program.methods.relayRootBundle(Array.from(root), Array.from(root)).accounts(relayRootBundleAccounts).rpc();

// Verify valid leaf
Expand Down Expand Up @@ -893,7 +928,7 @@ describe("svm_spoke.bundle", () => {
rootBundleIdBuffer.writeUInt32LE(rootBundleId);
const seeds = [Buffer.from("root_bundle"), state.toBuffer(), rootBundleIdBuffer];
const [rootBundle] = PublicKey.findProgramAddressSync(seeds, program.programId);
let relayRootBundleAccounts = { state, rootBundle, signer: owner };
let relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
await program.methods.relayRootBundle(Array.from(root), Array.from(root)).accounts(relayRootBundleAccounts).rpc();
const proofAsNumbers = proof.map((p) => Array.from(p));
const executeRelayerRefundLeafAccounts = {
Expand Down Expand Up @@ -969,7 +1004,7 @@ describe("svm_spoke.bundle", () => {
const [rootBundle] = PublicKey.findProgramAddressSync(seeds, program.programId);

// Relay root bundle
const relayRootBundleAccounts = { state, rootBundle, signer: owner };
const relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
await program.methods.relayRootBundle(Array.from(root), Array.from(root)).accounts(relayRootBundleAccounts).rpc();

const remainingAccounts = [{ pubkey: relayerTA, isWritable: true, isSigner: false }];
Expand Down Expand Up @@ -1043,7 +1078,7 @@ describe("svm_spoke.bundle", () => {
const [rootBundle] = PublicKey.findProgramAddressSync(seeds, program.programId);

// Relay root bundle
const relayRootBundleAccounts = { state, rootBundle, signer: owner };
const relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
await program.methods.relayRootBundle(Array.from(root), Array.from(root)).accounts(relayRootBundleAccounts).rpc();

const remainingAccounts = [
Expand Down Expand Up @@ -1146,7 +1181,7 @@ describe("svm_spoke.bundle", () => {
const [rootBundle] = PublicKey.findProgramAddressSync(seeds, program.programId);

// Relay root bundle
const relayRootBundleAccounts = { state, rootBundle, signer: owner };
const relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
await program.methods.relayRootBundle(Array.from(root), Array.from(root)).accounts(relayRootBundleAccounts).rpc();

// Pass refund addresses in remaining accounts.
Expand Down
2 changes: 1 addition & 1 deletion test/svm/SvmSpoke.RefundClaims.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ describe("svm_spoke.refund_claims", () => {
const [rootBundle] = PublicKey.findProgramAddressSync(seeds, program.programId);

// Relay root bundle
const relayRootBundleAccounts = { state, rootBundle, signer: owner };
const relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
await program.methods.relayRootBundle(Array.from(root), Array.from(root)).accounts(relayRootBundleAccounts).rpc();

// Pass claim account as relayer refund address.
Expand Down
2 changes: 1 addition & 1 deletion test/svm/SvmSpoke.SlowFill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ describe("svm_spoke.slow_fill", () => {
const relayerRefundRoot = crypto.randomBytes(32);

// Relay root bundle
const relayRootBundleAccounts = { state, rootBundle, signer: owner };
const relayRootBundleAccounts = { state, rootBundle, signer: owner, program: program.programId };
await program.methods
.relayRootBundle(Array.from(relayerRefundRoot), Array.from(slowRelayRoot))
.accounts(relayRootBundleAccounts)
Expand Down
1 change: 1 addition & 0 deletions test/svm/SvmSpoke.TokenBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ describe("svm_spoke.token_bridge", () => {
state,
rootBundle,
signer: owner,
program: program.programId,
};
await program.methods
.relayRootBundle(Array.from(root), Array.from(Buffer.alloc(32)))
Expand Down
Loading