Skip to content

Commit b7ddacc

Browse files
feat(svm): remove enabled deposit route check (#939)
* feat(svm): remove enabled deposit route check Signed-off-by: Reinis Martinsons <reinis@umaproject.org> * fix: remove create_vault ix Signed-off-by: Reinis Martinsons <reinis@umaproject.org> * Update scripts/svm/simpleDeposit.ts Co-authored-by: Chris Maree <christopher.maree@gmail.com> * fix: update comment Signed-off-by: Reinis Martinsons <reinis@umaproject.org> --------- Signed-off-by: Reinis Martinsons <reinis@umaproject.org> Co-authored-by: Chris Maree <christopher.maree@gmail.com>
1 parent 8bef3ca commit b7ddacc

20 files changed

+120
-1039
lines changed

Anchor.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ queryEvents = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/queryEvents.ts"
3030
queryEventsV2 = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/queryEventsV2.ts"
3131
initialize = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/initialize.ts"
3232
queryState = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/queryState.ts"
33-
enableRoute = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/enableRoute.ts"
34-
queryRoute = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/queryRoute.ts"
33+
createVault = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/createVault.ts"
34+
queryVault = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/queryVault.ts"
3535
simpleDeposit = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/simpleDeposit.ts"
3636
queryDeposits = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/queryDeposits.ts"
3737
queryFills = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/queryFills.ts"

programs/svm-spoke/src/error.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ use anchor_lang::prelude::*;
33
// Common Errors with EVM SpokePool.
44
#[error_code]
55
pub enum CommonError {
6-
#[msg("The route is not enabled!")]
7-
DisabledRoute,
86
#[msg("Invalid quote timestamp!")]
97
InvalidQuoteTimestamp,
108
#[msg("Ivalid fill deadline!")]

programs/svm-spoke/src/event.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,6 @@ pub struct PausedFills {
2121
pub is_paused: bool,
2222
}
2323

24-
#[event]
25-
pub struct EnabledDepositRoute {
26-
pub origin_token: Pubkey,
27-
pub destination_chain_id: u64,
28-
pub enabled: bool,
29-
}
30-
3124
#[event]
3225
pub struct RelayedRootBundle {
3326
pub root_bundle_id: u32,

programs/svm-spoke/src/instructions/admin.rs

Lines changed: 3 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
use anchor_lang::prelude::*;
2-
use anchor_spl::{
3-
associated_token::AssociatedToken,
4-
token_interface::{Mint, TokenAccount, TokenInterface},
5-
};
62

73
use crate::{
84
constants::DISCRIMINATOR_SIZE,
95
constraints::is_local_or_remote_owner,
106
error::SvmError,
117
event::{
12-
EmergencyDeletedRootBundle, EnabledDepositRoute, PausedDeposits, PausedFills, RelayedRootBundle,
13-
SetXDomainAdmin, TransferredOwnership,
8+
EmergencyDeletedRootBundle, PausedDeposits, PausedFills, RelayedRootBundle, SetXDomainAdmin,
9+
TransferredOwnership,
1410
},
15-
state::{RootBundle, Route, State},
11+
state::{RootBundle, State},
1612
utils::{initialize_current_time, set_seed},
1713
};
1814

@@ -136,67 +132,6 @@ pub fn set_cross_domain_admin(ctx: Context<SetCrossDomainAdmin>, cross_domain_ad
136132
Ok(())
137133
}
138134

139-
#[event_cpi]
140-
#[derive(Accounts)]
141-
#[instruction(origin_token: Pubkey, destination_chain_id: u64)]
142-
pub struct SetEnableRoute<'info> {
143-
#[account(constraint = is_local_or_remote_owner(&signer, &state) @ SvmError::NotOwner)]
144-
pub signer: Signer<'info>,
145-
146-
#[account(mut)]
147-
pub payer: Signer<'info>,
148-
149-
#[account(seeds = [b"state", state.seed.to_le_bytes().as_ref()], bump)]
150-
pub state: Account<'info, State>,
151-
152-
#[account(
153-
init_if_needed,
154-
payer = payer,
155-
space = DISCRIMINATOR_SIZE + Route::INIT_SPACE,
156-
seeds = [
157-
b"route",
158-
origin_token.as_ref(),
159-
state.seed.to_le_bytes().as_ref(),
160-
destination_chain_id.to_le_bytes().as_ref(),
161-
],
162-
bump
163-
)]
164-
pub route: Account<'info, Route>, // PDA to store route information for this particular token & chainId pair.
165-
166-
#[account(
167-
init_if_needed,
168-
payer = payer,
169-
associated_token::mint = origin_token_mint,
170-
associated_token::authority = state,
171-
associated_token::token_program = token_program
172-
)]
173-
pub vault: InterfaceAccount<'info, TokenAccount>, // ATA, owned by the state, to store the origin token for spoke.
174-
175-
#[account(
176-
mint::token_program = token_program,
177-
// IDL build fails when requiring address = origin_token for mint, thus using a custom constraint.
178-
constraint = origin_token_mint.key() == origin_token @ SvmError::InvalidMint
179-
)]
180-
pub origin_token_mint: InterfaceAccount<'info, Mint>,
181-
182-
pub token_program: Interface<'info, TokenInterface>,
183-
pub associated_token_program: Program<'info, AssociatedToken>,
184-
pub system_program: Program<'info, System>,
185-
}
186-
187-
pub fn set_enable_route(
188-
ctx: Context<SetEnableRoute>,
189-
origin_token: Pubkey,
190-
destination_chain_id: u64,
191-
enabled: bool,
192-
) -> Result<()> {
193-
ctx.accounts.route.enabled = enabled;
194-
195-
emit_cpi!(EnabledDepositRoute { origin_token, destination_chain_id, enabled });
196-
197-
Ok(())
198-
}
199-
200135
#[event_cpi]
201136
#[derive(Accounts)]
202137
pub struct RelayRootBundle<'info> {

programs/svm-spoke/src/instructions/deposit.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
constants::{MAX_EXCLUSIVITY_PERIOD_SECONDS, ZERO_DEPOSIT_ID},
1111
error::{CommonError, SvmError},
1212
event::FundsDeposited,
13-
state::{Route, State},
13+
state::State,
1414
utils::{get_current_time, get_unsafe_deposit_id, transfer_from},
1515
};
1616

@@ -36,13 +36,6 @@ pub struct Deposit<'info> {
3636
)]
3737
pub state: Account<'info, State>,
3838

39-
#[account(
40-
seeds = [b"route", input_token.as_ref(), state.seed.to_le_bytes().as_ref(), destination_chain_id.to_le_bytes().as_ref()],
41-
bump,
42-
constraint = route.enabled @ CommonError::DisabledRoute
43-
)]
44-
pub route: Account<'info, Route>,
45-
4639
#[account(
4740
mut,
4841
associated_token::mint = mint,

programs/svm-spoke/src/instructions/handle_receive_message.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,6 @@ fn translate_message(data: &Vec<u8>) -> Result<Vec<u8>> {
6969

7070
new_cross_domain_admin.encode_instruction_data("global:set_cross_domain_admin")
7171
}
72-
// The EVM function signature is setEnableRoute(address,uint256,bool).
73-
// The EVM Solana adapter translates this to the expected Solana format: setEnableRoute(bytes32,uint64,bool).
74-
s if s == utils::encode_solidity_selector("setEnableRoute(bytes32,uint64,bool)") => {
75-
let origin_token = Pubkey::new_from_array(utils::get_solidity_arg(data, 0)?);
76-
let destination_chain_id = utils::decode_solidity_uint64(&utils::get_solidity_arg(data, 1)?)?;
77-
let enabled = utils::decode_solidity_bool(&utils::get_solidity_arg(data, 2)?)?;
78-
79-
(origin_token, destination_chain_id, enabled).encode_instruction_data("global:set_enable_route")
80-
}
8172
s if s == utils::encode_solidity_selector("relayRootBundle(bytes32,bytes32)") => {
8273
let relayer_refund_root = utils::get_solidity_arg(data, 0)?;
8374
let slow_relay_root = utils::get_solidity_arg(data, 1)?;

programs/svm-spoke/src/lib.rs

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -123,34 +123,6 @@ pub mod svm_spoke {
123123
instructions::transfer_ownership(ctx, new_owner)
124124
}
125125

126-
/// Enables or disables a route for deposits from origin token to destination chain ID. Callable only by the owner.
127-
///
128-
/// ### Required Accounts:
129-
/// - signer (Signer): The account that must be the owner to authorize the route change.
130-
/// - payer (Signer): The account responsible for paying the transaction fees.
131-
/// - state (Writable): The Spoke state PDA. Seed: ["state",state.seed] where `seed` is 0 on mainnet.
132-
/// - route (Writable): PDA to store route information. Created on the first call, updated subsequently.
133-
/// Seed: ["route",origin_token,state.seed,destination_chain_id].
134-
/// - vault (Writable): ATA to hold the origin token for the associated route. Created on the first call.
135-
/// Authority must be set as the state, and mint must be the origin_token_mint.
136-
/// - origin_token_mint: The mint account for the origin token.
137-
/// - token_program: The token program.
138-
/// - associated_token_program: The associated token program.
139-
/// - system_program: The system program required for account creation.
140-
///
141-
/// ### Parameters:
142-
/// - origin_token: The public key of the origin token.
143-
/// - destination_chain_id: The chain ID of the destination.
144-
/// - enabled: Boolean indicating whether the route is enabled or disabled.
145-
pub fn set_enable_route(
146-
ctx: Context<SetEnableRoute>,
147-
origin_token: Pubkey,
148-
destination_chain_id: u64,
149-
enabled: bool,
150-
) -> Result<()> {
151-
instructions::set_enable_route(ctx, origin_token, destination_chain_id, enabled)
152-
}
153-
154126
/// Sets the cross-domain admin for the Spoke Pool. Only callable by owner. Used if Hubpool upgrades.
155127
///
156128
/// ### Required Accounts:
@@ -228,8 +200,6 @@ pub mod svm_spoke {
228200
/// ### Required Accounts:
229201
/// - signer (Signer): The account that authorizes the deposit.
230202
/// - state (Writable): Spoke state PDA. Seed: ["state",state.seed] where seed is 0 on mainnet.
231-
/// - route (Account): The route PDA for the particular bridged route in question. Validates a route is enabled.
232-
/// Seed: ["route",input_token,state.seed,destination_chain_id].
233203
/// - depositor_token_account (Writable): The depositor's ATA for the input token.
234204
/// - vault (Writable): Programs ATA for the associated input token. This is where the depositor's assets are sent.
235205
/// Authority must be the state.
@@ -246,8 +216,7 @@ pub mod svm_spoke {
246216
/// amount will be sent to the relayer on their repayment chain of choice as a refund following an optimistic
247217
/// challenge window in the HubPool, less a system fee.
248218
/// - output_amount: The amount of output tokens that the relayer will send to the recipient on the destination.
249-
/// - destination_chain_id: The destination chain identifier. Must be enabled along with the input token as a valid
250-
/// deposit route from this spoke pool or this transaction will revert.
219+
/// - destination_chain_id: The destination chain identifier where the fill should be made.
251220
/// - exclusive_relayer: The relayer that will be exclusively allowed to fill this deposit before the exclusivity
252221
/// deadline timestamp. This must be a valid, non-zero address if the exclusivity deadline is greater than the
253222
/// current block timestamp.
@@ -400,9 +369,6 @@ pub mod svm_spoke {
400369
/// instruction data due to message size constraints. Pass this program ID to represent None. When Some, this must
401370
/// be derived from the signer's public key with seed ["instruction_params",signer].
402371
/// - state (Writable): Spoke state PDA. Seed: ["state",state.seed] where seed is 0 on mainnet.
403-
/// - route (Account): The route PDA for the particular bridged route in question. Validates a route is enabled.
404-
/// Seed: ["route",input_token,state.seed,destination_chain_id].
405-
/// - vault (Writable): The ATA for refunded mint. Authority must be the state.
406372
/// - mint (Account): The mint of the output token, sent from the relayer to the recipient.
407373
/// - relayer_token_account (Writable): The relayer's ATA for the input token.
408374
/// - recipient_token_account (Writable): The recipient's ATA for the output token.

programs/svm-spoke/src/state/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@ pub mod fill;
22
pub mod instruction_params;
33
pub mod refund_account;
44
pub mod root_bundle;
5-
pub mod route;
65
pub mod state;
76
pub mod transfer_liability;
87

98
pub use fill::*;
109
pub use instruction_params::*;
1110
pub use refund_account::*;
1211
pub use root_bundle::*;
13-
pub use route::*;
1412
pub use state::*;
1513
pub use transfer_liability::*;

programs/svm-spoke/src/state/route.rs

Lines changed: 0 additions & 7 deletions
This file was deleted.

scripts/svm/createVault.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// This script is used by a chain admin to create a vault for a token on the Solana Spoke Pool. Note that this is a
2+
// permissionless operation, only requiring the caller to spend rent-exempt deposit to create the vault account that is
3+
// not recoverable. Similar to other chains, this enables one to deposit and fill non-whitelisted tokens.
4+
5+
import * as anchor from "@coral-xyz/anchor";
6+
import { AnchorProvider, BN } from "@coral-xyz/anchor";
7+
import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID, getOrCreateAssociatedTokenAccount } from "@solana/spl-token";
8+
import { PublicKey } from "@solana/web3.js";
9+
import yargs from "yargs";
10+
import { hideBin } from "yargs/helpers";
11+
import { getSpokePoolProgram } from "../../src/svm/web3-v1";
12+
13+
// Set up the provider
14+
const provider = AnchorProvider.env();
15+
anchor.setProvider(provider);
16+
const payer = (anchor.AnchorProvider.env().wallet as anchor.Wallet).payer;
17+
const program = getSpokePoolProgram(provider);
18+
const programId = program.programId;
19+
console.log("SVM-Spoke Program ID:", programId.toString());
20+
21+
// Parse arguments
22+
const argv = yargs(hideBin(process.argv))
23+
.option("seed", { type: "string", demandOption: true, describe: "Seed for the state account PDA" })
24+
.option("originToken", { type: "string", demandOption: true, describe: "Origin token public key" }).argv;
25+
26+
async function createVault(): Promise<void> {
27+
const resolvedArgv = await argv;
28+
const seed = new BN(resolvedArgv.seed);
29+
const originToken = new PublicKey(resolvedArgv.originToken);
30+
31+
// Define the state account PDA
32+
const [statePda, _] = PublicKey.findProgramAddressSync(
33+
[Buffer.from("state"), seed.toArrayLike(Buffer, "le", 8)],
34+
programId
35+
);
36+
37+
// Define the signer (replace with your actual signer)
38+
const signer = provider.wallet.publicKey;
39+
40+
console.log("Creating vault...");
41+
console.table([
42+
{ Property: "seed", Value: seed.toString() },
43+
{ Property: "originToken", Value: originToken.toString() },
44+
{ Property: "programId", Value: programId.toString() },
45+
{ Property: "providerPublicKey", Value: provider.wallet.publicKey.toString() },
46+
{ Property: "statePda", Value: statePda.toString() },
47+
]);
48+
49+
// Create ATA for the origin token to be stored by state (vault).
50+
const vault = await getOrCreateAssociatedTokenAccount(
51+
provider.connection,
52+
payer,
53+
originToken,
54+
statePda,
55+
true,
56+
"confirmed",
57+
{
58+
commitment: "confirmed",
59+
},
60+
TOKEN_PROGRAM_ID,
61+
ASSOCIATED_TOKEN_PROGRAM_ID
62+
);
63+
64+
console.log("Created vault:", vault.address.toString());
65+
}
66+
67+
// Run the createVault function
68+
createVault();

0 commit comments

Comments
 (0)