From 49d3d544f9bcddc943cfeadf31d579934b7643e8 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Sat, 20 Jul 2024 20:02:38 +0100 Subject: [PATCH 01/47] added bridge escrow contract Co-authored-by: doradelta " --- Anchor.toml | 3 + Cargo.lock | 43 +++++ Cargo.toml | 1 + solana/bridge-escrow/migrations/deploy.ts | 12 ++ .../programs/bridge-escrow/Cargo.toml | 63 +++++++ .../programs/bridge-escrow/Xargo.toml | 2 + .../programs/bridge-escrow/src/lib.rs | 155 ++++++++++++++++++ 7 files changed, 279 insertions(+) create mode 100644 solana/bridge-escrow/migrations/deploy.ts create mode 100644 solana/bridge-escrow/programs/bridge-escrow/Cargo.toml create mode 100644 solana/bridge-escrow/programs/bridge-escrow/Xargo.toml create mode 100644 solana/bridge-escrow/programs/bridge-escrow/src/lib.rs diff --git a/Anchor.toml b/Anchor.toml index b5c355d7..01dda00a 100644 --- a/Anchor.toml +++ b/Anchor.toml @@ -5,10 +5,12 @@ skip-lint = false [programs.devnet] restaking = "8n3FHwYxFgQCQc2FNFkwDUf9mcqupxXcCvgfHbApMLv3" solana_ibc = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT" +bridge-escrow = "A5ygmioT2hWFnxpPapY3XyDjwwfMDhnSP1Yxoynd5hs4" [programs.localnet] restaking = "8n3FHwYxFgQCQc2FNFkwDUf9mcqupxXcCvgfHbApMLv3" solana_ibc = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT" +bridge-escrow = "A5ygmioT2hWFnxpPapY3XyDjwwfMDhnSP1Yxoynd5hs4" [registry] url = "https://api.apr.dev" @@ -19,6 +21,7 @@ wallet = "~/.config/solana/id.json" [workspace] members = [ + "solana/bridge-escrow/program/bridge-escrow", "solana/restaking/programs/restaking", "solana/solana-ibc/programs/solana-ibc" ] diff --git a/Cargo.lock b/Cargo.lock index 9011eb52..ac2636ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -844,6 +844,49 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "bridge-escrow" +version = "0.0.3" +dependencies = [ + "anchor-client", + "anchor-lang", + "anchor-spl", + "anyhow", + "base64 0.21.7", + "bytemuck", + "cf-guest", + "derive_more", + "guestchain", + "hex-literal", + "ibc", + "ibc-client-tendermint-types", + "ibc-proto", + "ibc-testkit", + "insta", + "itertools", + "lib", + "linear-map", + "memory", + "primitive-types", + "prost", + "serde", + "serde_json", + "solana-allocator", + "solana-ibc", + "solana-signature-verifier", + "solana-trie", + "solana-write-account", + "spl-associated-token-account", + "spl-token", + "stdx", + "strum", + "tendermint", + "tendermint-light-client-verifier", + "trie-ids", + "uint", + "wasm", +] + [[package]] name = "brotli" version = "3.4.0" diff --git a/Cargo.toml b/Cargo.toml index 2daeb1b8..1ac8b89e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ rust-version = "1.71.0" members = [ "common/*", "solana/allocator", + "solana/bridge-escrow/programs/*", "solana/restaking/programs/*", "solana/signature-verifier", "solana/solana-ibc/programs/*", diff --git a/solana/bridge-escrow/migrations/deploy.ts b/solana/bridge-escrow/migrations/deploy.ts new file mode 100644 index 00000000..82fb175f --- /dev/null +++ b/solana/bridge-escrow/migrations/deploy.ts @@ -0,0 +1,12 @@ +// Migrations are an early feature. Currently, they're nothing more than this +// single deploy script that's invoked from the CLI, injecting a provider +// configured from the workspace's Anchor.toml. + +const anchor = require("@coral-xyz/anchor"); + +module.exports = async function (provider) { + // Configure client to use the provider. + anchor.setProvider(provider); + + // Add your deploy script here. +}; diff --git a/solana/bridge-escrow/programs/bridge-escrow/Cargo.toml b/solana/bridge-escrow/programs/bridge-escrow/Cargo.toml new file mode 100644 index 00000000..d14ac409 --- /dev/null +++ b/solana/bridge-escrow/programs/bridge-escrow/Cargo.toml @@ -0,0 +1,63 @@ +[package] +name = "bridge-escrow" +description = "Created with Anchor" +edition = "2021" +version.workspace = true + +[lib] +crate-type = ["cdylib", "lib"] +name = "bridge_escrow" + +[features] +# added so that we can compile this along with `solana-ibc` with mocks features. Currently unused. +mocks = [] +no-entrypoint = [] +no-idl = [] +no-log-ix-name = [] +cpi = ["no-entrypoint"] +default = [] + +[dependencies] +anchor-lang.workspace = true +anchor-spl = { workspace = true, features = ["metadata"] } +base64.workspace = true +bytemuck = { workspace = true, features = ["must_cast", "zeroable_atomics"] } +derive_more.workspace = true +hex-literal.workspace = true +ibc-client-tendermint-types.workspace = true +ibc-proto.workspace = true +ibc-testkit = { workspace = true, optional = true } +ibc.workspace = true +linear-map.workspace = true +primitive-types.workspace = true +prost.workspace = true +serde.workspace = true +serde_json.workspace = true +spl-associated-token-account.workspace = true +spl-token.workspace = true +strum.workspace = true +tendermint-light-client-verifier.workspace = true +tendermint.workspace = true +uint.workspace = true + +guestchain.workspace = true +cf-guest.workspace = true +lib = { workspace = true, features = ["solana-program"] } +memory.workspace = true +solana-allocator = { workspace = true, optional = true } +solana-signature-verifier = { workspace = true, features = ["guest", "library"] } +solana-trie.workspace = true +stdx.workspace = true +trie-ids = { workspace = true, features = ["borsh"] } +wasm = { workspace = true } +itertools = "0.10.5" +solana-ibc = { workspace = true, features = ["cpi"] } + +[dev-dependencies] +anchor-client.workspace = true +anyhow.workspace = true +ibc-testkit.workspace = true +insta.workspace = true + +lib = { workspace = true, features = ["test_utils"] } +solana-write-account = { workspace = true, features = ["library"] } diff --git a/solana/bridge-escrow/programs/bridge-escrow/Xargo.toml b/solana/bridge-escrow/programs/bridge-escrow/Xargo.toml new file mode 100644 index 00000000..475fb71e --- /dev/null +++ b/solana/bridge-escrow/programs/bridge-escrow/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs new file mode 100644 index 00000000..a6ee9d51 --- /dev/null +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -0,0 +1,155 @@ +use anchor_spl::token; +use anchor_lang::prelude::*; +use anchor_spl::token::{Token, TokenAccount, Transfer as SplTransfer, Mint}; +use ibc::apps::transfer::types::msgs::transfer::MsgTransfer; +use ibc::apps::transfer::types::packet::PacketData; +use ibc::apps::transfer::types::{PrefixedCoin, PrefixedDenom}; +use ibc::core::channel::types::timeout::TimeoutHeight::At; +use ibc::core::client::types::Height; +use ibc::core::host::types::identifiers::{ChannelId, PortId}; +use ibc::core::primitives::Timestamp; +use ibc::primitives::Signer as IbcSigner; +use lib::hash::CryptoHash; +use solana_ibc::cpi::send_transfer; +use solana_ibc::program::SolanaIbc; +use std::str::FromStr; +use solana_ibc::chain; +use solana_ibc::cpi::accounts::SendTransfer; +use solana_ibc::storage::PrivateStorage; + + +declare_id!("A5ygmioT2hWFnxpPapY3XyDjwwfMDhnSP1Yxoynd5hs4"); + +#[program] +pub mod bridge_escrow { + use super::*; + + pub fn send_funds_to_user( + ctx: Context, + amount: u64, + hashed_full_denom: CryptoHash, + ) -> Result<()> { + let destination_account = &ctx.accounts.destination_token_account; + let source_account = &ctx.accounts.source_token_account; + let token_program = &ctx.accounts.spl_token_program; + let authority = &ctx.accounts.authority; + + // Transfer tokens from solver to user + let cpi_accounts = SplTransfer { + from: source_account.to_account_info().clone(), + to: destination_account.to_account_info().clone(), + authority: authority.to_account_info().clone(), + }; + let cpi_program = token_program.to_account_info(); + + let my_custom_memo = format!( + "{},{},{},{}", + source_account.key(), + destination_account.key(), + authority.key(), + token_program.key() + ); + + // Invoke SPL token transfer + token::transfer(CpiContext::new(cpi_program, cpi_accounts), amount)?; + + // Cross-chain transfer + memo + let transfer_ctx = CpiContext::new( + ctx.accounts.ibc_program.to_account_info().clone(), + SendTransfer { + sender: authority.to_account_info().clone(), + receiver: ctx.accounts.receiver.clone(), + storage: ctx.accounts.storage.to_account_info().clone(), + trie: ctx.accounts.trie.to_account_info().clone(), + chain: ctx.accounts.chain.to_account_info().clone(), + mint_authority: ctx + .accounts + .mint_authority + .as_ref() + .map(|ma| ma.to_account_info()), + token_mint: ctx + .accounts + .token_mint + .as_ref() + .map(|tm| tm.to_account_info()), + escrow_account: ctx + .accounts + .escrow_account + .as_ref() + .map(|ea| ea.to_account_info()), + receiver_token_account: ctx + .accounts + .receiver_token_account + .as_ref() + .map(|rta| rta.to_account_info()), + fee_collector: ctx + .accounts + .fee_collector + .as_ref() + .map(|fc| fc.to_account_info()), + token_program: Some( + ctx.accounts.spl_token_program.to_account_info().clone(), + ), + system_program: ctx + .accounts + .system_program + .to_account_info() + .clone(), + }, + ); + + let memo = "{\"forward\":{\"receiver\":\"0x4c22af5da4a849a8f39be00eb1b44676ac5c9060\",\"port\":\"transfer\",\"channel\":\"channel-52\",\"timeout\":600000000000000,\"next\":{\"memo\":\"my-custom-msg\"}}}".to_string(); + let memo = memo.replace("my-custom-msg", &my_custom_memo); + + // MsgTransfer + let msg = MsgTransfer { + port_id_on_a: PortId::from_str("transfer").unwrap(), + chan_id_on_a: ChannelId::from_str("channel-1").unwrap(), + packet_data: PacketData { + token: PrefixedCoin { + denom: PrefixedDenom::from_str("address_of_token_minted").unwrap(), // token only owned by this PDA + amount: 1.into(), + }, + sender: IbcSigner::from( + ctx.accounts.authority.key().to_string(), + ), + receiver: String::from("pfm").into(), + memo: memo.into(), + }, + timeout_height_on_b: At(Height::new(2018502000, 29340670).unwrap()), + timeout_timestamp_on_b: Timestamp::from_nanoseconds(1000000000000000000).unwrap(), + }; + + send_transfer(transfer_ctx, hashed_full_denom, msg)?; + + Ok(()) + } +} + +// Accounts for transferring SPL tokens +#[derive(Accounts)] +pub struct SplTokenTransfer<'info> { + pub authority: Signer<'info>, + // SPL Token Transfer Accounts + #[account(mut)] + pub source_token_account: Account<'info, TokenAccount>, + #[account(mut)] + pub destination_token_account: Account<'info, TokenAccount>, + pub spl_token_program: Program<'info, Token>, + // Cross-chain Transfer Accounts + pub ibc_program: Program<'info, SolanaIbc>, // Use IbcProgram here + pub receiver: Option>, + pub storage: Account<'info, PrivateStorage>, + /// CHECK: + pub trie: UncheckedAccount<'info>, + pub chain: Box>, + /// CHECK: + pub mint_authority: Option>, + pub token_mint: Option>>, + pub escrow_account: Option>>, + pub receiver_token_account: Option>>, + /// CHECK: + pub fee_collector: Option>, + pub token_program: Program<'info, Token>, + pub system_program: Program<'info, System>, +} \ No newline at end of file From 45e42c0c40ceb2b36d1eca8e47cbb24abaa5681d Mon Sep 17 00:00:00 2001 From: dhruvja Date: Sat, 20 Jul 2024 20:02:38 +0100 Subject: [PATCH 02/47] added bridge escrow contract Co-authored-by: doradelta --- Anchor.toml | 3 + Cargo.lock | 43 +++++ Cargo.toml | 1 + solana/bridge-escrow/migrations/deploy.ts | 12 ++ .../programs/bridge-escrow/Cargo.toml | 63 +++++++ .../programs/bridge-escrow/Xargo.toml | 2 + .../programs/bridge-escrow/src/lib.rs | 155 ++++++++++++++++++ 7 files changed, 279 insertions(+) create mode 100644 solana/bridge-escrow/migrations/deploy.ts create mode 100644 solana/bridge-escrow/programs/bridge-escrow/Cargo.toml create mode 100644 solana/bridge-escrow/programs/bridge-escrow/Xargo.toml create mode 100644 solana/bridge-escrow/programs/bridge-escrow/src/lib.rs diff --git a/Anchor.toml b/Anchor.toml index b5c355d7..01dda00a 100644 --- a/Anchor.toml +++ b/Anchor.toml @@ -5,10 +5,12 @@ skip-lint = false [programs.devnet] restaking = "8n3FHwYxFgQCQc2FNFkwDUf9mcqupxXcCvgfHbApMLv3" solana_ibc = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT" +bridge-escrow = "A5ygmioT2hWFnxpPapY3XyDjwwfMDhnSP1Yxoynd5hs4" [programs.localnet] restaking = "8n3FHwYxFgQCQc2FNFkwDUf9mcqupxXcCvgfHbApMLv3" solana_ibc = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT" +bridge-escrow = "A5ygmioT2hWFnxpPapY3XyDjwwfMDhnSP1Yxoynd5hs4" [registry] url = "https://api.apr.dev" @@ -19,6 +21,7 @@ wallet = "~/.config/solana/id.json" [workspace] members = [ + "solana/bridge-escrow/program/bridge-escrow", "solana/restaking/programs/restaking", "solana/solana-ibc/programs/solana-ibc" ] diff --git a/Cargo.lock b/Cargo.lock index 9011eb52..ac2636ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -844,6 +844,49 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "bridge-escrow" +version = "0.0.3" +dependencies = [ + "anchor-client", + "anchor-lang", + "anchor-spl", + "anyhow", + "base64 0.21.7", + "bytemuck", + "cf-guest", + "derive_more", + "guestchain", + "hex-literal", + "ibc", + "ibc-client-tendermint-types", + "ibc-proto", + "ibc-testkit", + "insta", + "itertools", + "lib", + "linear-map", + "memory", + "primitive-types", + "prost", + "serde", + "serde_json", + "solana-allocator", + "solana-ibc", + "solana-signature-verifier", + "solana-trie", + "solana-write-account", + "spl-associated-token-account", + "spl-token", + "stdx", + "strum", + "tendermint", + "tendermint-light-client-verifier", + "trie-ids", + "uint", + "wasm", +] + [[package]] name = "brotli" version = "3.4.0" diff --git a/Cargo.toml b/Cargo.toml index 2daeb1b8..1ac8b89e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ rust-version = "1.71.0" members = [ "common/*", "solana/allocator", + "solana/bridge-escrow/programs/*", "solana/restaking/programs/*", "solana/signature-verifier", "solana/solana-ibc/programs/*", diff --git a/solana/bridge-escrow/migrations/deploy.ts b/solana/bridge-escrow/migrations/deploy.ts new file mode 100644 index 00000000..82fb175f --- /dev/null +++ b/solana/bridge-escrow/migrations/deploy.ts @@ -0,0 +1,12 @@ +// Migrations are an early feature. Currently, they're nothing more than this +// single deploy script that's invoked from the CLI, injecting a provider +// configured from the workspace's Anchor.toml. + +const anchor = require("@coral-xyz/anchor"); + +module.exports = async function (provider) { + // Configure client to use the provider. + anchor.setProvider(provider); + + // Add your deploy script here. +}; diff --git a/solana/bridge-escrow/programs/bridge-escrow/Cargo.toml b/solana/bridge-escrow/programs/bridge-escrow/Cargo.toml new file mode 100644 index 00000000..d14ac409 --- /dev/null +++ b/solana/bridge-escrow/programs/bridge-escrow/Cargo.toml @@ -0,0 +1,63 @@ +[package] +name = "bridge-escrow" +description = "Created with Anchor" +edition = "2021" +version.workspace = true + +[lib] +crate-type = ["cdylib", "lib"] +name = "bridge_escrow" + +[features] +# added so that we can compile this along with `solana-ibc` with mocks features. Currently unused. +mocks = [] +no-entrypoint = [] +no-idl = [] +no-log-ix-name = [] +cpi = ["no-entrypoint"] +default = [] + +[dependencies] +anchor-lang.workspace = true +anchor-spl = { workspace = true, features = ["metadata"] } +base64.workspace = true +bytemuck = { workspace = true, features = ["must_cast", "zeroable_atomics"] } +derive_more.workspace = true +hex-literal.workspace = true +ibc-client-tendermint-types.workspace = true +ibc-proto.workspace = true +ibc-testkit = { workspace = true, optional = true } +ibc.workspace = true +linear-map.workspace = true +primitive-types.workspace = true +prost.workspace = true +serde.workspace = true +serde_json.workspace = true +spl-associated-token-account.workspace = true +spl-token.workspace = true +strum.workspace = true +tendermint-light-client-verifier.workspace = true +tendermint.workspace = true +uint.workspace = true + +guestchain.workspace = true +cf-guest.workspace = true +lib = { workspace = true, features = ["solana-program"] } +memory.workspace = true +solana-allocator = { workspace = true, optional = true } +solana-signature-verifier = { workspace = true, features = ["guest", "library"] } +solana-trie.workspace = true +stdx.workspace = true +trie-ids = { workspace = true, features = ["borsh"] } +wasm = { workspace = true } +itertools = "0.10.5" +solana-ibc = { workspace = true, features = ["cpi"] } + +[dev-dependencies] +anchor-client.workspace = true +anyhow.workspace = true +ibc-testkit.workspace = true +insta.workspace = true + +lib = { workspace = true, features = ["test_utils"] } +solana-write-account = { workspace = true, features = ["library"] } diff --git a/solana/bridge-escrow/programs/bridge-escrow/Xargo.toml b/solana/bridge-escrow/programs/bridge-escrow/Xargo.toml new file mode 100644 index 00000000..475fb71e --- /dev/null +++ b/solana/bridge-escrow/programs/bridge-escrow/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs new file mode 100644 index 00000000..a6ee9d51 --- /dev/null +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -0,0 +1,155 @@ +use anchor_spl::token; +use anchor_lang::prelude::*; +use anchor_spl::token::{Token, TokenAccount, Transfer as SplTransfer, Mint}; +use ibc::apps::transfer::types::msgs::transfer::MsgTransfer; +use ibc::apps::transfer::types::packet::PacketData; +use ibc::apps::transfer::types::{PrefixedCoin, PrefixedDenom}; +use ibc::core::channel::types::timeout::TimeoutHeight::At; +use ibc::core::client::types::Height; +use ibc::core::host::types::identifiers::{ChannelId, PortId}; +use ibc::core::primitives::Timestamp; +use ibc::primitives::Signer as IbcSigner; +use lib::hash::CryptoHash; +use solana_ibc::cpi::send_transfer; +use solana_ibc::program::SolanaIbc; +use std::str::FromStr; +use solana_ibc::chain; +use solana_ibc::cpi::accounts::SendTransfer; +use solana_ibc::storage::PrivateStorage; + + +declare_id!("A5ygmioT2hWFnxpPapY3XyDjwwfMDhnSP1Yxoynd5hs4"); + +#[program] +pub mod bridge_escrow { + use super::*; + + pub fn send_funds_to_user( + ctx: Context, + amount: u64, + hashed_full_denom: CryptoHash, + ) -> Result<()> { + let destination_account = &ctx.accounts.destination_token_account; + let source_account = &ctx.accounts.source_token_account; + let token_program = &ctx.accounts.spl_token_program; + let authority = &ctx.accounts.authority; + + // Transfer tokens from solver to user + let cpi_accounts = SplTransfer { + from: source_account.to_account_info().clone(), + to: destination_account.to_account_info().clone(), + authority: authority.to_account_info().clone(), + }; + let cpi_program = token_program.to_account_info(); + + let my_custom_memo = format!( + "{},{},{},{}", + source_account.key(), + destination_account.key(), + authority.key(), + token_program.key() + ); + + // Invoke SPL token transfer + token::transfer(CpiContext::new(cpi_program, cpi_accounts), amount)?; + + // Cross-chain transfer + memo + let transfer_ctx = CpiContext::new( + ctx.accounts.ibc_program.to_account_info().clone(), + SendTransfer { + sender: authority.to_account_info().clone(), + receiver: ctx.accounts.receiver.clone(), + storage: ctx.accounts.storage.to_account_info().clone(), + trie: ctx.accounts.trie.to_account_info().clone(), + chain: ctx.accounts.chain.to_account_info().clone(), + mint_authority: ctx + .accounts + .mint_authority + .as_ref() + .map(|ma| ma.to_account_info()), + token_mint: ctx + .accounts + .token_mint + .as_ref() + .map(|tm| tm.to_account_info()), + escrow_account: ctx + .accounts + .escrow_account + .as_ref() + .map(|ea| ea.to_account_info()), + receiver_token_account: ctx + .accounts + .receiver_token_account + .as_ref() + .map(|rta| rta.to_account_info()), + fee_collector: ctx + .accounts + .fee_collector + .as_ref() + .map(|fc| fc.to_account_info()), + token_program: Some( + ctx.accounts.spl_token_program.to_account_info().clone(), + ), + system_program: ctx + .accounts + .system_program + .to_account_info() + .clone(), + }, + ); + + let memo = "{\"forward\":{\"receiver\":\"0x4c22af5da4a849a8f39be00eb1b44676ac5c9060\",\"port\":\"transfer\",\"channel\":\"channel-52\",\"timeout\":600000000000000,\"next\":{\"memo\":\"my-custom-msg\"}}}".to_string(); + let memo = memo.replace("my-custom-msg", &my_custom_memo); + + // MsgTransfer + let msg = MsgTransfer { + port_id_on_a: PortId::from_str("transfer").unwrap(), + chan_id_on_a: ChannelId::from_str("channel-1").unwrap(), + packet_data: PacketData { + token: PrefixedCoin { + denom: PrefixedDenom::from_str("address_of_token_minted").unwrap(), // token only owned by this PDA + amount: 1.into(), + }, + sender: IbcSigner::from( + ctx.accounts.authority.key().to_string(), + ), + receiver: String::from("pfm").into(), + memo: memo.into(), + }, + timeout_height_on_b: At(Height::new(2018502000, 29340670).unwrap()), + timeout_timestamp_on_b: Timestamp::from_nanoseconds(1000000000000000000).unwrap(), + }; + + send_transfer(transfer_ctx, hashed_full_denom, msg)?; + + Ok(()) + } +} + +// Accounts for transferring SPL tokens +#[derive(Accounts)] +pub struct SplTokenTransfer<'info> { + pub authority: Signer<'info>, + // SPL Token Transfer Accounts + #[account(mut)] + pub source_token_account: Account<'info, TokenAccount>, + #[account(mut)] + pub destination_token_account: Account<'info, TokenAccount>, + pub spl_token_program: Program<'info, Token>, + // Cross-chain Transfer Accounts + pub ibc_program: Program<'info, SolanaIbc>, // Use IbcProgram here + pub receiver: Option>, + pub storage: Account<'info, PrivateStorage>, + /// CHECK: + pub trie: UncheckedAccount<'info>, + pub chain: Box>, + /// CHECK: + pub mint_authority: Option>, + pub token_mint: Option>>, + pub escrow_account: Option>>, + pub receiver_token_account: Option>>, + /// CHECK: + pub fee_collector: Option>, + pub token_program: Program<'info, Token>, + pub system_program: Program<'info, System>, +} \ No newline at end of file From f7d4780e1ff2cce942ea9ad4ed3e9e2e38c82908 Mon Sep 17 00:00:00 2001 From: doradelta <64730977+doradelta@users.noreply.github.com> Date: Tue, 6 Aug 2024 19:51:37 +0200 Subject: [PATCH 03/47] bridge-scrow -> tests.rs (#355) Co-authored-by: dhruvja --- Anchor.toml | 20 +- solana-test.sh | 1 + .../programs/bridge-escrow/Cargo.toml | 1 + .../programs/bridge-escrow/src/lib.rs | 109 +++++---- .../programs/bridge-escrow/src/tests.rs | 209 ++++++++++++++++++ .../restaking/programs/restaking/src/lib.rs | 2 +- .../solana-ibc/programs/solana-ibc/src/lib.rs | 2 +- 7 files changed, 285 insertions(+), 59 deletions(-) create mode 100644 solana/bridge-escrow/programs/bridge-escrow/src/tests.rs diff --git a/Anchor.toml b/Anchor.toml index 01dda00a..e82664d1 100644 --- a/Anchor.toml +++ b/Anchor.toml @@ -1,30 +1,28 @@ +[toolchain] + [features] seeds = false skip-lint = false [programs.devnet] -restaking = "8n3FHwYxFgQCQc2FNFkwDUf9mcqupxXcCvgfHbApMLv3" -solana_ibc = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT" bridge-escrow = "A5ygmioT2hWFnxpPapY3XyDjwwfMDhnSP1Yxoynd5hs4" +restaking = "9JkWjSfc5Yb5EdTwhxHDx6rh8usXYVFm9KFwqzskVE8t" +solana_ibc = "3JvDhxt87SqKwNSuBPWWSRsfSxzkjzofDh1B6DioqfQ3" [programs.localnet] -restaking = "8n3FHwYxFgQCQc2FNFkwDUf9mcqupxXcCvgfHbApMLv3" -solana_ibc = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT" bridge-escrow = "A5ygmioT2hWFnxpPapY3XyDjwwfMDhnSP1Yxoynd5hs4" +restaking = "9JkWjSfc5Yb5EdTwhxHDx6rh8usXYVFm9KFwqzskVE8t" +solana_ibc = "3JvDhxt87SqKwNSuBPWWSRsfSxzkjzofDh1B6DioqfQ3" [registry] url = "https://api.apr.dev" [provider] -cluster = "localnet" -wallet = "~/.config/solana/id.json" +cluster = "Localnet" +wallet = "/Users/dhruvjain/.config/solana/id.json" [workspace] -members = [ - "solana/bridge-escrow/program/bridge-escrow", - "solana/restaking/programs/restaking", - "solana/solana-ibc/programs/solana-ibc" -] +members = ["solana/bridge-escrow/programs/bridge-escrow", "solana/restaking/programs/restaking", "solana/solana-ibc/programs/solana-ibc"] [scripts] test = "./solana-test.sh" diff --git a/solana-test.sh b/solana-test.sh index 5d37e362..629a12c4 100755 --- a/solana-test.sh +++ b/solana-test.sh @@ -10,5 +10,6 @@ cd ../.. solana program deploy target/deploy/write.so solana program deploy target/deploy/sigverify.so cargo test --lib -- --nocapture --include-ignored ::anchor +cargo test --lib -- --nocapture --include-ignored ::escrow find solana/restaking/tests/ -name '*.ts' \ -exec yarn run ts-mocha -p ./tsconfig.json -t 1000000 {} + diff --git a/solana/bridge-escrow/programs/bridge-escrow/Cargo.toml b/solana/bridge-escrow/programs/bridge-escrow/Cargo.toml index d14ac409..a61403b7 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/Cargo.toml +++ b/solana/bridge-escrow/programs/bridge-escrow/Cargo.toml @@ -18,6 +18,7 @@ cpi = ["no-entrypoint"] default = [] [dependencies] +anyhow.workspace = true anchor-lang.workspace = true anchor-spl = { workspace = true, features = ["metadata"] } base64.workspace = true diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index a6ee9d51..b4e5c401 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -1,6 +1,9 @@ -use anchor_spl::token; +use std::str::FromStr; + use anchor_lang::prelude::*; -use anchor_spl::token::{Token, TokenAccount, Transfer as SplTransfer, Mint}; +use anchor_spl::associated_token::AssociatedToken; +use anchor_spl::token; +use anchor_spl::token::{Mint, Token, TokenAccount, Transfer as SplTransfer}; use ibc::apps::transfer::types::msgs::transfer::MsgTransfer; use ibc::apps::transfer::types::packet::PacketData; use ibc::apps::transfer::types::{PrefixedCoin, PrefixedDenom}; @@ -10,15 +13,16 @@ use ibc::core::host::types::identifiers::{ChannelId, PortId}; use ibc::core::primitives::Timestamp; use ibc::primitives::Signer as IbcSigner; use lib::hash::CryptoHash; -use solana_ibc::cpi::send_transfer; -use solana_ibc::program::SolanaIbc; -use std::str::FromStr; use solana_ibc::chain; use solana_ibc::cpi::accounts::SendTransfer; +use solana_ibc::cpi::send_transfer; +use solana_ibc::program::SolanaIbc; use solana_ibc::storage::PrivateStorage; +#[cfg(test)] +mod tests; -declare_id!("A5ygmioT2hWFnxpPapY3XyDjwwfMDhnSP1Yxoynd5hs4"); +declare_id!("8t5dMbZuGsUtcX7JZpCN8kfPnt8e6VSc3XGepVTMUig4"); #[program] pub mod bridge_escrow { @@ -31,7 +35,7 @@ pub mod bridge_escrow { ) -> Result<()> { let destination_account = &ctx.accounts.destination_token_account; let source_account = &ctx.accounts.source_token_account; - let token_program = &ctx.accounts.spl_token_program; + let token_program = &ctx.accounts.token_program; let authority = &ctx.accounts.authority; // Transfer tokens from solver to user @@ -53,42 +57,32 @@ pub mod bridge_escrow { // Invoke SPL token transfer token::transfer(CpiContext::new(cpi_program, cpi_accounts), amount)?; + let token_mint = ctx.accounts.token_mint.to_account_info(); + // Cross-chain transfer + memo let transfer_ctx = CpiContext::new( ctx.accounts.ibc_program.to_account_info().clone(), SendTransfer { sender: authority.to_account_info().clone(), - receiver: ctx.accounts.receiver.clone(), + receiver: Some(ctx.accounts.receiver.to_account_info()), storage: ctx.accounts.storage.to_account_info().clone(), trie: ctx.accounts.trie.to_account_info().clone(), chain: ctx.accounts.chain.to_account_info().clone(), - mint_authority: ctx - .accounts - .mint_authority - .as_ref() - .map(|ma| ma.to_account_info()), - token_mint: ctx - .accounts - .token_mint - .as_ref() - .map(|tm| tm.to_account_info()), - escrow_account: ctx - .accounts - .escrow_account - .as_ref() - .map(|ea| ea.to_account_info()), - receiver_token_account: ctx - .accounts - .receiver_token_account - .as_ref() - .map(|rta| rta.to_account_info()), - fee_collector: ctx - .accounts - .fee_collector - .as_ref() - .map(|fc| fc.to_account_info()), + mint_authority: Some( + ctx.accounts.mint_authority.to_account_info(), + ), + token_mint: Some(ctx.accounts.token_mint.to_account_info()), + escrow_account: Some( + ctx.accounts.escrow_account.to_account_info(), + ), + receiver_token_account: Some( + ctx.accounts.receiver_token_account.to_account_info(), + ), + fee_collector: Some( + ctx.accounts.fee_collector.to_account_info(), + ), token_program: Some( - ctx.accounts.spl_token_program.to_account_info().clone(), + ctx.accounts.token_program.to_account_info().clone(), ), system_program: ctx .accounts @@ -98,16 +92,23 @@ pub mod bridge_escrow { }, ); - let memo = "{\"forward\":{\"receiver\":\"0x4c22af5da4a849a8f39be00eb1b44676ac5c9060\",\"port\":\"transfer\",\"channel\":\"channel-52\",\"timeout\":600000000000000,\"next\":{\"memo\":\"my-custom-msg\"}}}".to_string(); + let memo = "{\"forward\":{\"receiver\":\"\ + 0x4c22af5da4a849a8f39be00eb1b44676ac5c9060\",\"port\":\"\ + transfer\",\"channel\":\"channel-52\",\"timeout\":\ + 600000000000000,\"next\":{\"memo\":\"my-custom-msg\"}}}" + .to_string(); let memo = memo.replace("my-custom-msg", &my_custom_memo); // MsgTransfer let msg = MsgTransfer { port_id_on_a: PortId::from_str("transfer").unwrap(), - chan_id_on_a: ChannelId::from_str("channel-1").unwrap(), + chan_id_on_a: ChannelId::from_str("channel-0").unwrap(), packet_data: PacketData { token: PrefixedCoin { - denom: PrefixedDenom::from_str("address_of_token_minted").unwrap(), // token only owned by this PDA + denom: PrefixedDenom::from_str( + &token_mint.key().to_string(), + ) + .unwrap(), // token only owned by this PDA amount: 1.into(), }, sender: IbcSigner::from( @@ -117,7 +118,10 @@ pub mod bridge_escrow { memo: memo.into(), }, timeout_height_on_b: At(Height::new(2018502000, 29340670).unwrap()), - timeout_timestamp_on_b: Timestamp::from_nanoseconds(1000000000000000000).unwrap(), + timeout_timestamp_on_b: Timestamp::from_nanoseconds( + 1000000000000000000, + ) + .unwrap(), }; send_transfer(transfer_ctx, hashed_full_denom, msg)?; @@ -129,27 +133,40 @@ pub mod bridge_escrow { // Accounts for transferring SPL tokens #[derive(Accounts)] pub struct SplTokenTransfer<'info> { + #[account(mut)] pub authority: Signer<'info>, // SPL Token Transfer Accounts #[account(mut)] pub source_token_account: Account<'info, TokenAccount>, + // #[account(init_if_needed, payer = authority, associated_token::mint = token_mint, associated_token::authority = destination)] #[account(mut)] pub destination_token_account: Account<'info, TokenAccount>, - pub spl_token_program: Program<'info, Token>, // Cross-chain Transfer Accounts pub ibc_program: Program<'info, SolanaIbc>, // Use IbcProgram here - pub receiver: Option>, + #[account(mut)] + /// CHECK: + pub receiver: AccountInfo<'info>, + #[account(mut)] pub storage: Account<'info, PrivateStorage>, /// CHECK: + #[account(mut)] pub trie: UncheckedAccount<'info>, + #[account(mut)] pub chain: Box>, /// CHECK: - pub mint_authority: Option>, - pub token_mint: Option>>, - pub escrow_account: Option>>, - pub receiver_token_account: Option>>, + #[account(mut)] + pub mint_authority: UncheckedAccount<'info>, + #[account(mut)] + pub token_mint: Box>, + /// CHECK: + #[account(mut)] + pub escrow_account: UncheckedAccount<'info>, + #[account(mut)] + pub receiver_token_account: Box>, /// CHECK: - pub fee_collector: Option>, + #[account(mut)] + pub fee_collector: UncheckedAccount<'info>, pub token_program: Program<'info, Token>, + pub associated_token_program: Program<'info, AssociatedToken>, pub system_program: Program<'info, System>, -} \ No newline at end of file +} diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs new file mode 100644 index 00000000..f75f5e4d --- /dev/null +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -0,0 +1,209 @@ +use std::rc::Rc; +use std::str::FromStr; +use std::thread::sleep; +use std::time::Duration; + +use anchor_client::solana_client::rpc_client::RpcClient; +use anchor_client::solana_client::rpc_config::RpcSendTransactionConfig; +use anchor_client::solana_sdk::commitment_config::CommitmentConfig; +use anchor_client::solana_sdk::compute_budget::ComputeBudgetInstruction; +use anchor_client::solana_sdk::pubkey::Pubkey; +use anchor_client::solana_sdk::signature::{ + Keypair, Signature, Signer as SolanaSigner, +}; +use anchor_client::{Client, Cluster}; +use anchor_spl::associated_token::get_associated_token_address; +use anyhow::Result; +use ibc::apps::transfer::types::{PrefixedCoin, PrefixedDenom}; +use spl_token::instruction::initialize_mint2; +use spl_token::solana_program::system_instruction::create_account; + +const MINT_AMOUNT: u64 = 1_000_000_000; + +fn airdrop(client: &RpcClient, account: Pubkey, lamports: u64) -> Signature { + let balance_before = client.get_balance(&account).unwrap(); + println!("This is balance before {}", balance_before); + let airdrop_signature = client.request_airdrop(&account, lamports).unwrap(); + sleep(Duration::from_secs(2)); + println!("This is airdrop signature {}", airdrop_signature); + + let balance_after = client.get_balance(&account).unwrap(); + println!("This is balance after {}", balance_after); + assert_eq!(balance_before + lamports, balance_after); + airdrop_signature +} + +#[test] +#[ignore = "Requires local validator to run"] +fn escrow_bridge_program() -> Result<()> { + // Setup the client and wallet + let payer = Rc::new(Keypair::new()); + + let client = Client::new_with_options( + Cluster::Localnet, + payer.clone(), + CommitmentConfig::processed(), + ); + + let program = client.program(crate::ID)?; + let sol_rpc_client = program.rpc(); + + let authority = Rc::new(Keypair::new()); + let lamports = 2_000_000_000; + + let receiver = Rc::new(Keypair::new()); + let mint_keypair = Keypair::new(); + let native_token_mint_key = mint_keypair.pubkey(); + + let program_rpc = program.rpc(); + + airdrop(&program_rpc, authority.pubkey(), lamports); + // airdrop(&program_rpc, fee_collector, lamports); + airdrop(&program_rpc, receiver.pubkey(), lamports); + + /* + * Creating Token Mint + */ + println!("\nCreating a token mint"); + + let create_account_ix = create_account( + &authority.pubkey(), + &native_token_mint_key, + sol_rpc_client.get_minimum_balance_for_rent_exemption(82).unwrap(), + 82, + &anchor_spl::token::ID, + ); + + let create_mint_ix = initialize_mint2( + &anchor_spl::token::ID, + &native_token_mint_key, + &authority.pubkey(), + Some(&authority.pubkey()), + 6, + ) + .expect("invalid mint instruction"); + + let create_token_acc_ix = spl_associated_token_account::instruction::create_associated_token_account(&authority.pubkey(), &authority.pubkey(), &native_token_mint_key, &anchor_spl::token::ID); + let create_token_acc_ix_2 = spl_associated_token_account::instruction::create_associated_token_account(&authority.pubkey(), &receiver.pubkey(), &native_token_mint_key, &anchor_spl::token::ID); + let associated_token_addr = get_associated_token_address( + &authority.pubkey(), + &native_token_mint_key, + ); + let mint_ix = spl_token::instruction::mint_to( + &anchor_spl::token::ID, + &native_token_mint_key, + &associated_token_addr, + &authority.pubkey(), + &[&authority.pubkey()], + MINT_AMOUNT, + ) + .unwrap(); + + let tx = program + .request() + .instruction(create_account_ix) + .instruction(create_mint_ix) + .instruction(create_token_acc_ix) + .instruction(create_token_acc_ix_2) + .instruction(mint_ix) + .payer(authority.clone()) + .signer(&*authority) + .signer(&mint_keypair) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..RpcSendTransactionConfig::default() + })?; + + println!(" Signature: {}", tx); + + let hashed_full_denom = lib::hash::CryptoHash::digest( + &native_token_mint_key.to_string().as_bytes(), + ); + + println!("Native token mint {}", native_token_mint_key); + println!("hashed full denom {}", hashed_full_denom); + + let x = PrefixedCoin { + denom: PrefixedDenom::from_str(&native_token_mint_key.to_string()) + .unwrap(), // token only owned by this PDA + amount: 1.into(), + }; + + println!("full denom {:?}", x.denom.to_string()); + println!( + "hashed full denom {:?}", + lib::hash::CryptoHash::digest(x.denom.to_string().as_bytes()) + ); + + // Derive the necessary accounts + let (storage, _bump_storage) = Pubkey::find_program_address( + &[solana_ibc::SOLANA_IBC_STORAGE_SEED], + &solana_ibc::ID, + ); + let (trie, _bump_trie) = + Pubkey::find_program_address(&[solana_ibc::TRIE_SEED], &solana_ibc::ID); + let (chain, _bump_chain) = Pubkey::find_program_address( + &[solana_ibc::CHAIN_SEED], + &solana_ibc::ID, + ); + let (mint_authority, _bump_mint_authority) = Pubkey::find_program_address( + &[solana_ibc::MINT_ESCROW_SEED], + &solana_ibc::ID, + ); + let (escrow_account, _bump_escrow_account) = Pubkey::find_program_address( + &[solana_ibc::ESCROW, &hashed_full_denom.as_slice()], + &solana_ibc::ID, + ); + + let receiver_token_account = get_associated_token_address( + &authority.pubkey(), + &native_token_mint_key, + ); + let (fee_collector, _bump_fee_collector) = + Pubkey::find_program_address(&[solana_ibc::FEE_SEED], &solana_ibc::ID); + + let system_program = anchor_lang::system_program::ID; + + // Amount to transfer + let amount = 1000000; // Example amount + + let destination_token_account = get_associated_token_address( + &receiver.pubkey(), + &native_token_mint_key, + ); + + // Build and send the transaction to call send_funds_to_user + println!("\nSending funds to user"); + let sig = program + .request() + .instruction(ComputeBudgetInstruction::set_compute_unit_limit( + 1_000_000, + )) + .accounts(crate::accounts::SplTokenTransfer { + authority: authority.pubkey(), + source_token_account: receiver_token_account, + destination_token_account, + ibc_program: solana_ibc::ID, + receiver: receiver.pubkey(), + storage, + trie, + chain, + mint_authority, + token_mint: native_token_mint_key, + escrow_account, + receiver_token_account, + fee_collector, + token_program: anchor_spl::token::ID, + associated_token_program: anchor_spl::associated_token::ID, + system_program, + }) + .args(crate::instruction::SendFundsToUser { amount, hashed_full_denom }) + .payer(authority.clone()) + .signer(&*authority) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..RpcSendTransactionConfig::default() + })?; + println!(" Signature: {sig}"); + Ok(()) +} diff --git a/solana/restaking/programs/restaking/src/lib.rs b/solana/restaking/programs/restaking/src/lib.rs index 8be7de0d..4bcf295e 100644 --- a/solana/restaking/programs/restaking/src/lib.rs +++ b/solana/restaking/programs/restaking/src/lib.rs @@ -16,7 +16,7 @@ use constants::{ VAULT_PARAMS_SEED, VAULT_SEED, }; -declare_id!("8n3FHwYxFgQCQc2FNFkwDUf9mcqupxXcCvgfHbApMLv3"); +declare_id!("9JkWjSfc5Yb5EdTwhxHDx6rh8usXYVFm9KFwqzskVE8t"); #[program] pub mod restaking { diff --git a/solana/solana-ibc/programs/solana-ibc/src/lib.rs b/solana/solana-ibc/programs/solana-ibc/src/lib.rs index aa58c9c9..ab0070b2 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/lib.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/lib.rs @@ -33,7 +33,7 @@ pub const WSOL_ADDRESS: &str = "So11111111111111111111111111111111111111112"; pub const MINIMUM_FEE_ACCOUNT_BALANCE: u64 = solana_program::native_token::LAMPORTS_PER_SOL; -declare_id!("2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"); +declare_id!("3JvDhxt87SqKwNSuBPWWSRsfSxzkjzofDh1B6DioqfQ3"); #[cfg(not(feature = "mocks"))] mod relayer { From aadd44b5ffda34abe89986bebcc10dc89f00b0a2 Mon Sep 17 00:00:00 2001 From: banegil Date: Wed, 7 Aug 2024 19:04:02 +0200 Subject: [PATCH 04/47] test push alberto --- .../programs/bridge-escrow/src/lib.rs | 202 +++++++----------- 1 file changed, 75 insertions(+), 127 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index b4e5c401..5d5d4f93 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -28,145 +28,93 @@ declare_id!("8t5dMbZuGsUtcX7JZpCN8kfPnt8e6VSc3XGepVTMUig4"); pub mod bridge_escrow { use super::*; - pub fn send_funds_to_user( - ctx: Context, - amount: u64, - hashed_full_denom: CryptoHash, + pub fn initialize( + ctx: Context, ) -> Result<()> { - let destination_account = &ctx.accounts.destination_token_account; - let source_account = &ctx.accounts.source_token_account; - let token_program = &ctx.accounts.token_program; - let authority = &ctx.accounts.authority; - - // Transfer tokens from solver to user - let cpi_accounts = SplTransfer { - from: source_account.to_account_info().clone(), - to: destination_account.to_account_info().clone(), - authority: authority.to_account_info().clone(), - }; - let cpi_program = token_program.to_account_info(); - - let my_custom_memo = format!( - "{},{},{},{}", - source_account.key(), - destination_account.key(), - authority.key(), - token_program.key() - ); - - // Invoke SPL token transfer - token::transfer(CpiContext::new(cpi_program, cpi_accounts), amount)?; - - let token_mint = ctx.accounts.token_mint.to_account_info(); + // store the auctioner + let auctioner = &mut ctx.accounts.auctioner; + auctioner.authority = *ctx.accounts.authority.key; + Ok(()) + } - // Cross-chain transfer + memo - let transfer_ctx = CpiContext::new( - ctx.accounts.ibc_program.to_account_info().clone(), - SendTransfer { - sender: authority.to_account_info().clone(), - receiver: Some(ctx.accounts.receiver.to_account_info()), - storage: ctx.accounts.storage.to_account_info().clone(), - trie: ctx.accounts.trie.to_account_info().clone(), - chain: ctx.accounts.chain.to_account_info().clone(), - mint_authority: Some( - ctx.accounts.mint_authority.to_account_info(), - ), - token_mint: Some(ctx.accounts.token_mint.to_account_info()), - escrow_account: Some( - ctx.accounts.escrow_account.to_account_info(), - ), - receiver_token_account: Some( - ctx.accounts.receiver_token_account.to_account_info(), - ), - fee_collector: Some( - ctx.accounts.fee_collector.to_account_info(), - ), - token_program: Some( - ctx.accounts.token_program.to_account_info().clone(), - ), - system_program: ctx - .accounts - .system_program - .to_account_info() - .clone(), - }, + pub fn store_intent( + ctx: Context, + intent_id: String, + user_in: Pubkey, + token_in: Pubkey, + amount_in: u64, + token_out: String, + amount_out: String, + winner_solver: Pubkey, + ) -> Result<()> { + // verify if caller is auctioner + let auctioner = &ctx.accounts.auctioner; + require!( + *ctx.accounts.authority.key == auctioner.authority, + ErrorCode::Unauthorized ); - let memo = "{\"forward\":{\"receiver\":\"\ - 0x4c22af5da4a849a8f39be00eb1b44676ac5c9060\",\"port\":\"\ - transfer\",\"channel\":\"channel-52\",\"timeout\":\ - 600000000000000,\"next\":{\"memo\":\"my-custom-msg\"}}}" - .to_string(); - let memo = memo.replace("my-custom-msg", &my_custom_memo); - - // MsgTransfer - let msg = MsgTransfer { - port_id_on_a: PortId::from_str("transfer").unwrap(), - chan_id_on_a: ChannelId::from_str("channel-0").unwrap(), - packet_data: PacketData { - token: PrefixedCoin { - denom: PrefixedDenom::from_str( - &token_mint.key().to_string(), - ) - .unwrap(), // token only owned by this PDA - amount: 1.into(), - }, - sender: IbcSigner::from( - ctx.accounts.authority.key().to_string(), - ), - receiver: String::from("pfm").into(), - memo: memo.into(), - }, - timeout_height_on_b: At(Height::new(2018502000, 29340670).unwrap()), - timeout_timestamp_on_b: Timestamp::from_nanoseconds( - 1000000000000000000, - ) - .unwrap(), - }; - - send_transfer(transfer_ctx, hashed_full_denom, msg)?; + // save intent on a PDA derived from the auctioner account + let intent = &mut ctx.accounts.intent; + intent.intent_id = intent_id; + intent.user = *ctx.accounts.authority.key; + intent.user_in = user_in; + intent.token_in = token_in; + intent.amount_in = amount_in; + intent.token_out = token_out; + intent.amount_out = amount_out; + intent.winner_solver = winner_solver; Ok(()) } } -// Accounts for transferring SPL tokens +// Define the Auctioner account +#[account] +pub struct Auctioner { + pub authority: Pubkey, +} + +// Define the Intent account +#[account] +pub struct Intent { + pub intent_id: String, + pub user: Pubkey, + pub user_in: Pubkey, + pub token_in: Pubkey, + pub amount_in: u64, + pub token_out: String, // 20 bytes + pub amount_out: String, // 20 bytes + pub winner_solver: Pubkey, +} + +// Define the context for initializing the program #[derive(Accounts)] -pub struct SplTokenTransfer<'info> { +#[instruction()] +pub struct Initialize<'info> { + #[account(init, seeds = [b"auctioner"], bump, payer = authority, space = 8 + 32)] + pub auctioner: Account<'info, Auctioner>, #[account(mut)] pub authority: Signer<'info>, - // SPL Token Transfer Accounts - #[account(mut)] - pub source_token_account: Account<'info, TokenAccount>, - // #[account(init_if_needed, payer = authority, associated_token::mint = token_mint, associated_token::authority = destination)] - #[account(mut)] - pub destination_token_account: Account<'info, TokenAccount>, - // Cross-chain Transfer Accounts - pub ibc_program: Program<'info, SolanaIbc>, // Use IbcProgram here - #[account(mut)] - /// CHECK: - pub receiver: AccountInfo<'info>, - #[account(mut)] - pub storage: Account<'info, PrivateStorage>, - /// CHECK: - #[account(mut)] - pub trie: UncheckedAccount<'info>, - #[account(mut)] - pub chain: Box>, - /// CHECK: - #[account(mut)] - pub mint_authority: UncheckedAccount<'info>, - #[account(mut)] - pub token_mint: Box>, - /// CHECK: - #[account(mut)] - pub escrow_account: UncheckedAccount<'info>, - #[account(mut)] - pub receiver_token_account: Box>, - /// CHECK: + pub system_program: Program<'info, System>, +} + +// Define the context for storing intent +#[derive(Accounts)] +#[instruction(intent_id: String)] +pub struct StoreIntent<'info> { + #[account(init_if_needed, seeds = [b"intent", auctioner.key().as_ref(), intent_id.as_bytes()], bump, payer = authority, space = 8 + 32 * 4 + 8 + 40 + 20 + 20)] + pub intent: Account<'info, Intent>, + #[account(seeds = [b"auctioner"], bump)] + pub auctioner: Account<'info, Auctioner>, #[account(mut)] - pub fee_collector: UncheckedAccount<'info>, - pub token_program: Program<'info, Token>, - pub associated_token_program: Program<'info, AssociatedToken>, + pub authority: Signer<'info>, pub system_program: Program<'info, System>, } + +// Define custom errors +#[error_code] +pub enum ErrorCode { + #[msg("You are not authorized to perform this action.")] + Unauthorized, +} From f7a5ec86bb92096b957ccee66d5e5746d4ceede2 Mon Sep 17 00:00:00 2001 From: banegil Date: Thu, 8 Aug 2024 17:09:13 +0200 Subject: [PATCH 05/47] on_receive_transfer & send_funds_to_user escrow contract --- .../programs/bridge-escrow/src/lib.rs | 260 +++++++++++++++++- .../programs/bridge-escrow/src/tests.rs | 64 ++--- 2 files changed, 290 insertions(+), 34 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 5d5d4f93..1bad0a2b 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -19,6 +19,9 @@ use solana_ibc::cpi::send_transfer; use solana_ibc::program::SolanaIbc; use solana_ibc::storage::PrivateStorage; +const DUMMY: &str = "0x36dd1bfe89d409f869fabbe72c3cf72ea8b460f6"; +const BRIDGE_CONTRACT_PUBKEY: &str = "your_bridge_contract_pubkey"; + #[cfg(test)] mod tests; @@ -67,6 +70,166 @@ pub mod bridge_escrow { Ok(()) } + + pub fn on_receive_transfer( + ctx: Context, + msg: MsgTransfer, + ) -> Result<()> { + // Ensure the message is from the bridge contract + let bridge_pubkey = Pubkey::from_str(BRIDGE_CONTRACT_PUBKEY).map_err(|_| ErrorCode::InvalidBridgeContract)?; + require!( + ctx.accounts.bridge_contract.key == &bridge_pubkey, + ErrorCode::InvalidBridgeContract + ); + + // Extract and validate the memo + let parts: Vec<&str> = msg.packet_data.memo.to_string().split(',').collect(); + if parts.len() != 3 { + return Err(ErrorCode::InvalidAmount); + } + let (token_str, solver_str, amount_str) = (parts[0], parts[1], parts[2]); + + require!( + msg.packet_data.token.denom.base_denom.to_string() == DUMMY, + ErrorCode::InvalidDenom + ); + + let token_pubkey = Pubkey::from_str(token_str).map_err(|_| ErrorCode::InvalidTokenAddress)?; + let solver_pubkey = Pubkey::from_str(solver_str).map_err(|_| ErrorCode::InvalidSolverAddress)?; + let amount: u64 = amount_str.parse().map_err(|_| ErrorCode::InvalidAmount)?; + + // Perform the token transfer + let cpi_accounts = Transfer { + from: ctx.accounts.token_account.to_account_info(), + to: ctx.accounts.receiver.to_account_info(), + authority: ctx.accounts.receiver.to_account_info(), + }; + + let cpi_program = ctx.accounts.token_program.to_account_info(); + let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts); + + token::transfer(cpi_ctx, amount)?; + + Ok(()) + } + + pub fn send_funds_to_user( + ctx: Context, + hashed_full_denom: CryptoHash, + solver_out: String, + single_domain: bool + ) -> Result<()> { + let intent = &ctx.accounts.intent; + require!( + *ctx.accounts.authority.key == intent.winner_solver, + ErrorCode::Unauthorized + ); + + let token_program = &ctx.accounts.token_program; + let authority = &ctx.accounts.authority; + + // Transfer tokens from Solver to User + let cpi_accounts = SplTransfer { + from: ctx.accounts.solver_token_in_account.to_account_info().clone(), + to: ctx.accounts.user_token_in_account.to_account_info().clone(), + authority: authority.to_account_info().clone(), + }; + let cpi_program = token_program.to_account_info(); + token::transfer(CpiContext::new(cpi_program, cpi_accounts), intent.amount_in)?; + + if single_domain { + // Transfer tokens from Solver to User + let cpi_accounts = SplTransfer { + from: ctx.accounts.user_token_out_account.to_account_info().clone(), + to: ctx.accounts.solver_token_out_account.to_account_info().clone(), + authority: authority.to_account_info().clone(), + }; + let cpi_program = token_program.to_account_info(); + token::transfer(CpiContext::new(cpi_program, cpi_accounts), intent.amount_in)?; + } + else { + let token_mint = ctx.accounts.token_mint.to_account_info(); + + let my_custom_memo = format!( + "{},{},{}", + intent.token_out, + intent.amount_out, + solver_out + ); + + // Cross-chain transfer + memo + let transfer_ctx = CpiContext::new( + ctx.accounts.ibc_program.to_account_info().clone(), + SendTransfer { + sender: authority.to_account_info().clone(), + receiver: Some(ctx.accounts.receiver.to_account_info()), + storage: ctx.accounts.storage.to_account_info().clone(), + trie: ctx.accounts.trie.to_account_info().clone(), + chain: ctx.accounts.chain.to_account_info().clone(), + mint_authority: Some( + ctx.accounts.mint_authority.to_account_info(), + ), + token_mint: Some(ctx.accounts.token_mint.to_account_info()), + escrow_account: Some( + ctx.accounts.escrow_account.to_account_info(), + ), + receiver_token_account: Some( + ctx.accounts.receiver_token_account.to_account_info(), + ), + fee_collector: Some( + ctx.accounts.fee_collector.to_account_info(), + ), + token_program: Some( + ctx.accounts.token_program.to_account_info().clone(), + ), + system_program: ctx + .accounts + .system_program + .to_account_info() + .clone(), + }, + ); + + let memo = "{\"forward\":{\"receiver\":\"\ + 0x4c22af5da4a849a8f39be00eb1b44676ac5c9060\",\"port\":\"\ + transfer\",\"channel\":\"channel-52\",\"timeout\":\ + 600000000000000,\"next\":{\"memo\":\"my-custom-msg\"}}}" + .to_string(); + let memo = memo.replace("my-custom-msg", &my_custom_memo); + + // MsgTransfer + let msg = MsgTransfer { + port_id_on_a: PortId::from_str("transfer").unwrap(), + chan_id_on_a: ChannelId::from_str("channel-0").unwrap(), + packet_data: PacketData { + token: PrefixedCoin { + denom: PrefixedDenom::from_str( + &token_mint.key().to_string(), + ) + .unwrap(), // token only owned by this PDA + amount: 1.into(), + }, + sender: IbcSigner::from( + ctx.accounts.authority.key().to_string(), + ), + receiver: String::from("pfm").into(), + memo: memo.into(), + }, + timeout_height_on_b: At(Height::new(2018502000, 29340670).unwrap()), + timeout_timestamp_on_b: Timestamp::from_nanoseconds( + 1000000000000000000, + ) + .unwrap(), + }; + + send_transfer(transfer_ctx, hashed_full_denom, msg)?; + } + + // delete intent + + Ok(()) + } + } // Define the Auctioner account @@ -75,7 +238,7 @@ pub struct Auctioner { pub authority: Pubkey, } -// Define the Intent account +// Define the Intent account with space calculation #[account] pub struct Intent { pub intent_id: String, @@ -88,6 +251,18 @@ pub struct Intent { pub winner_solver: Pubkey, } +impl Intent { + pub const LEN: usize = 8 // discriminator + + 4 + 40 // intent_id: String (assuming a max length of 40 bytes) + + 32 // user: Pubkey + + 32 // user_in: Pubkey + + 32 // token_in: Pubkey + + 8 // amount_in: u64 + + 4 + 20 // token_out: String (assuming a max length of 20 bytes) + + 4 + 20 // amount_out: String (assuming a max length of 20 bytes) + + 32; // winner_solver: Pubkey +} + // Define the context for initializing the program #[derive(Accounts)] #[instruction()] @@ -103,18 +278,99 @@ pub struct Initialize<'info> { #[derive(Accounts)] #[instruction(intent_id: String)] pub struct StoreIntent<'info> { - #[account(init_if_needed, seeds = [b"intent", auctioner.key().as_ref(), intent_id.as_bytes()], bump, payer = authority, space = 8 + 32 * 4 + 8 + 40 + 20 + 20)] + #[account(init_if_needed, seeds = [b"intent", intent_id.as_bytes()], bump, payer = authority, space = Intent::LEN)] + pub intent: Account<'info, Intent>, + #[account(seeds = [b"auctioner"], bump)] + pub auctioner: Account<'info, Auctioner>, + #[account(mut)] + pub authority: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[derive(Accounts)] +pub struct ReceiveTransferContext<'info> { + #[account(mut)] + pub receiver: Signer<'info>, + pub bridge_contract: AccountInfo<'info>, + pub token_program: Program<'info, Token>, + #[account(mut)] + pub token_account: Account<'info, TokenAccount>, +} + +// Accounts for transferring SPL tokens +#[derive(Accounts)] +#[instruction(intent_id: String)] +pub struct SplTokenTransfer<'info> { + // Intent reading + #[account(seeds = [b"intent", intent_id.as_bytes()], bump)] pub intent: Account<'info, Intent>, #[account(seeds = [b"auctioner"], bump)] pub auctioner: Account<'info, Auctioner>, + #[account(mut)] pub authority: Signer<'info>, + // Solver -> User SPL Token Transfer Accounts + #[account(mut)] + pub user_token_in_account: Account<'info, TokenAccount>, + // #[account(init_if_needed, payer = authority, associated_token::mint = token_mint, associated_token::authority = destination)] + #[account(mut)] + pub solver_token_in_account: Account<'info, TokenAccount>, + + + // User -> Solver SPL Token Transfer Accounts + #[account(mut)] + pub solver_token_out_account: Account<'info, TokenAccount>, + // #[account(init_if_needed, payer = authority, associated_token::mint = token_mint, associated_token::authority = destination)] + #[account(mut)] + pub user_token_out_account: Account<'info, TokenAccount>, + + + // Cross-chain Transfer Accounts + pub ibc_program: Program<'info, SolanaIbc>, // Use IbcProgram here + #[account(mut)] + /// CHECK: + pub receiver: AccountInfo<'info>, + #[account(mut)] + pub storage: Account<'info, PrivateStorage>, + /// CHECK: + #[account(mut)] + pub trie: UncheckedAccount<'info>, + #[account(mut)] + pub chain: Box>, + /// CHECK: + #[account(mut)] + pub mint_authority: UncheckedAccount<'info>, + #[account(mut)] + pub token_mint: Box>, + /// CHECK: + #[account(mut)] + pub escrow_account: UncheckedAccount<'info>, + #[account(mut)] + pub receiver_token_account: Box>, + /// CHECK: + #[account(mut)] + pub fee_collector: UncheckedAccount<'info>, + pub token_program: Program<'info, Token>, + pub associated_token_program: Program<'info, AssociatedToken>, pub system_program: Program<'info, System>, } + // Define custom errors #[error_code] pub enum ErrorCode { #[msg("You are not authorized to perform this action.")] Unauthorized, + #[msg("The provided bridge contract is invalid.")] + InvalidBridgeContract, + #[msg("Invalid token address in the memo.")] + InvalidTokenAddress, + #[msg("Invalid solver address in the memo.")] + InvalidSolverAddress, + #[msg("Invalid amount in the memo.")] + InvalidAmount, + #[msg("Token transfer failed.")] + TransferFailed, } + + diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index f75f5e4d..2da24769 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -173,37 +173,37 @@ fn escrow_bridge_program() -> Result<()> { ); // Build and send the transaction to call send_funds_to_user - println!("\nSending funds to user"); - let sig = program - .request() - .instruction(ComputeBudgetInstruction::set_compute_unit_limit( - 1_000_000, - )) - .accounts(crate::accounts::SplTokenTransfer { - authority: authority.pubkey(), - source_token_account: receiver_token_account, - destination_token_account, - ibc_program: solana_ibc::ID, - receiver: receiver.pubkey(), - storage, - trie, - chain, - mint_authority, - token_mint: native_token_mint_key, - escrow_account, - receiver_token_account, - fee_collector, - token_program: anchor_spl::token::ID, - associated_token_program: anchor_spl::associated_token::ID, - system_program, - }) - .args(crate::instruction::SendFundsToUser { amount, hashed_full_denom }) - .payer(authority.clone()) - .signer(&*authority) - .send_with_spinner_and_config(RpcSendTransactionConfig { - skip_preflight: true, - ..RpcSendTransactionConfig::default() - })?; - println!(" Signature: {sig}"); + // println!("\nSending funds to user"); + // let sig = program + // .request() + // .instruction(ComputeBudgetInstruction::set_compute_unit_limit( + // 1_000_000, + // )) + // .accounts(crate::accounts::SplTokenTransfer { + // authority: authority.pubkey(), + // solver_token_in_account: receiver_token_account, + // user_token_in_account, + // ibc_program: solana_ibc::ID, + // receiver: receiver.pubkey(), + // storage, + // trie, + // chain, + // mint_authority, + // token_mint: native_token_mint_key, + // escrow_account, + // receiver_token_account, + // fee_collector, + // token_program: anchor_spl::token::ID, + // associated_token_program: anchor_spl::associated_token::ID, + // system_program, + // }) + // .args(crate::instruction::SendFundsToUser { amount, hashed_full_denom }) + // .payer(authority.clone()) + // .signer(&*authority) + // .send_with_spinner_and_config(RpcSendTransactionConfig { + // skip_preflight: true, + // ..RpcSendTransactionConfig::default() + // })?; + // println!(" Signature: {sig}"); Ok(()) } From 44cdd868d2c3ad6baa8c082897ec9a9e23cd87bd Mon Sep 17 00:00:00 2001 From: banegil Date: Thu, 8 Aug 2024 17:32:13 +0200 Subject: [PATCH 06/47] on_receive_transfer & send_funds_to_user escrow contract --- .../programs/bridge-escrow/src/lib.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 1bad0a2b..79e30819 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -83,23 +83,21 @@ pub mod bridge_escrow { ); // Extract and validate the memo - let parts: Vec<&str> = msg.packet_data.memo.to_string().split(',').collect(); - if parts.len() != 3 { - return Err(ErrorCode::InvalidAmount); - } - let (token_str, solver_str, amount_str) = (parts[0], parts[1], parts[2]); + let memo = msg.packet_data.memo.to_string(); + let parts: Vec<&str> = memo.split(',').collect(); + let (from_token_account, to_token_account, amount_str) = (parts[0], parts[1], parts[2]); require!( msg.packet_data.token.denom.base_denom.to_string() == DUMMY, ErrorCode::InvalidDenom ); - let token_pubkey = Pubkey::from_str(token_str).map_err(|_| ErrorCode::InvalidTokenAddress)?; - let solver_pubkey = Pubkey::from_str(solver_str).map_err(|_| ErrorCode::InvalidSolverAddress)?; + let from_to_pubkey = Pubkey::from_str(from_token_account).map_err(|_| ErrorCode::InvalidTokenAddress)?; + let to_token_pubkey = Pubkey::from_str(to_token_account).map_err(|_| ErrorCode::InvalidSolverAddress)?; let amount: u64 = amount_str.parse().map_err(|_| ErrorCode::InvalidAmount)?; // Perform the token transfer - let cpi_accounts = Transfer { + let cpi_accounts = SplTransfer { from: ctx.accounts.token_account.to_account_info(), to: ctx.accounts.receiver.to_account_info(), authority: ctx.accounts.receiver.to_account_info(), @@ -291,6 +289,7 @@ pub struct StoreIntent<'info> { pub struct ReceiveTransferContext<'info> { #[account(mut)] pub receiver: Signer<'info>, + /// CHECK: pub bridge_contract: AccountInfo<'info>, pub token_program: Program<'info, Token>, #[account(mut)] @@ -371,6 +370,8 @@ pub enum ErrorCode { InvalidAmount, #[msg("Token transfer failed.")] TransferFailed, + #[msg("Denom is not DUMMY token")] + InvalidDenom, } From 30ecf73274a99f9d681e440a211d3e524c686445 Mon Sep 17 00:00:00 2001 From: banegil Date: Thu, 8 Aug 2024 19:32:50 +0200 Subject: [PATCH 07/47] on_receive_transfer & send_funds_to_user escrow contract --- .../programs/bridge-escrow/src/lib.rs | 100 ++++++++++++------ 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 79e30819..6ea544cb 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -18,9 +18,10 @@ use solana_ibc::cpi::accounts::SendTransfer; use solana_ibc::cpi::send_transfer; use solana_ibc::program::SolanaIbc; use solana_ibc::storage::PrivateStorage; +use anchor_lang::solana_program; const DUMMY: &str = "0x36dd1bfe89d409f869fabbe72c3cf72ea8b460f6"; -const BRIDGE_CONTRACT_PUBKEY: &str = "your_bridge_contract_pubkey"; +// const BRIDGE_CONTRACT_PUBKEY: &str = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"; #[cfg(test)] mod tests; @@ -31,6 +32,25 @@ declare_id!("8t5dMbZuGsUtcX7JZpCN8kfPnt8e6VSc3XGepVTMUig4"); pub mod bridge_escrow { use super::*; + pub fn escrow_funds( + ctx: Context, + amount: u64, + ) -> Result<()> { + // Transfer SPL tokens from the user's account to the auctioner's account + let cpi_accounts = SplTransfer { + from: ctx.accounts.user_token_account.to_account_info(), + to: ctx.accounts.auctioner_token_account.to_account_info(), + authority: ctx.accounts.user.to_account_info(), + }; + + let cpi_program = ctx.accounts.token_program.to_account_info(); + let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts); + + token::transfer(cpi_ctx, amount)?; + + Ok(()) + } + pub fn initialize( ctx: Context, ) -> Result<()> { @@ -71,36 +91,37 @@ pub mod bridge_escrow { Ok(()) } + // ONLY bridge contract should call this function + /* + I assume this need to be done outside the Program to get the accounts + + // Extract and validate the memo + let memo = msg.packet_data.memo.to_string(); + let parts: Vec<&str> = memo.split(',').collect(); + let (token_mint, amount, solver) = (parts[0], parts[1], parts[2]); + + ctx.accounts.auctioner = get_token_account(token_mint, auctioner); + ctx.accounts.solver = get_token_account(token_mint, solver); + */ pub fn on_receive_transfer( ctx: Context, msg: MsgTransfer, ) -> Result<()> { - // Ensure the message is from the bridge contract - let bridge_pubkey = Pubkey::from_str(BRIDGE_CONTRACT_PUBKEY).map_err(|_| ErrorCode::InvalidBridgeContract)?; - require!( - ctx.accounts.bridge_contract.key == &bridge_pubkey, - ErrorCode::InvalidBridgeContract - ); - // Extract and validate the memo let memo = msg.packet_data.memo.to_string(); let parts: Vec<&str> = memo.split(',').collect(); - let (from_token_account, to_token_account, amount_str) = (parts[0], parts[1], parts[2]); - + require!( msg.packet_data.token.denom.base_denom.to_string() == DUMMY, ErrorCode::InvalidDenom ); + let amount: u64 = parts[1].parse().map_err(|_| ErrorCode::InvalidAmount)?; - let from_to_pubkey = Pubkey::from_str(from_token_account).map_err(|_| ErrorCode::InvalidTokenAddress)?; - let to_token_pubkey = Pubkey::from_str(to_token_account).map_err(|_| ErrorCode::InvalidSolverAddress)?; - let amount: u64 = amount_str.parse().map_err(|_| ErrorCode::InvalidAmount)?; - - // Perform the token transfer + // Transfer tokens from Auctioner to Solver let cpi_accounts = SplTransfer { - from: ctx.accounts.token_account.to_account_info(), - to: ctx.accounts.receiver.to_account_info(), - authority: ctx.accounts.receiver.to_account_info(), + from: ctx.accounts.auctioner.to_account_info(), + to: ctx.accounts.solver.to_account_info(), + authority: ctx.accounts.auctioner.to_account_info(), }; let cpi_program = ctx.accounts.token_program.to_account_info(); @@ -111,6 +132,7 @@ pub mod bridge_escrow { Ok(()) } + // this function is called by Solver pub fn send_funds_to_user( ctx: Context, hashed_full_denom: CryptoHash, @@ -129,16 +151,16 @@ pub mod bridge_escrow { // Transfer tokens from Solver to User let cpi_accounts = SplTransfer { from: ctx.accounts.solver_token_in_account.to_account_info().clone(), - to: ctx.accounts.user_token_in_account.to_account_info().clone(), + to: ctx.accounts.auctioner_token_in_account.to_account_info().clone(), authority: authority.to_account_info().clone(), }; let cpi_program = token_program.to_account_info(); token::transfer(CpiContext::new(cpi_program, cpi_accounts), intent.amount_in)?; if single_domain { - // Transfer tokens from Solver to User + // Transfer tokens from Auctioner to Solver let cpi_accounts = SplTransfer { - from: ctx.accounts.user_token_out_account.to_account_info().clone(), + from: ctx.accounts.auctioner_token_out_account.to_account_info().clone(), to: ctx.accounts.solver_token_out_account.to_account_info().clone(), authority: authority.to_account_info().clone(), }; @@ -223,8 +245,11 @@ pub mod bridge_escrow { send_transfer(transfer_ctx, hashed_full_denom, msg)?; } - // delete intent - + // Delete intent by closing the account + let intent_account_info = &mut ctx.accounts.intent.to_account_info(); + **intent_account_info.try_borrow_mut_lamports()? = 0; + intent_account_info.data.borrow_mut().fill(0); + Ok(()) } @@ -251,7 +276,7 @@ pub struct Intent { impl Intent { pub const LEN: usize = 8 // discriminator - + 4 + 40 // intent_id: String (assuming a max length of 40 bytes) + + 4 + 8 // intent_id: String (assuming a max length of 8 bytes) + 32 // user: Pubkey + 32 // user_in: Pubkey + 32 // token_in: Pubkey @@ -287,10 +312,14 @@ pub struct StoreIntent<'info> { #[derive(Accounts)] pub struct ReceiveTransferContext<'info> { + #[account(seeds = [b"auctioner"], bump)] + pub auctioner: Account<'info, Auctioner>, #[account(mut)] - pub receiver: Signer<'info>, - /// CHECK: - pub bridge_contract: AccountInfo<'info>, + pub solver: Signer<'info>, + #[account(address = solana_program::sysvar::instructions::ID)] + /// CHECK: Used for getting the caller program id to verify if the right + /// program is calling the method. + instruction: UncheckedAccount<'info>, pub token_program: Program<'info, Token>, #[account(mut)] pub token_account: Account<'info, TokenAccount>, @@ -305,12 +334,12 @@ pub struct SplTokenTransfer<'info> { pub intent: Account<'info, Intent>, #[account(seeds = [b"auctioner"], bump)] pub auctioner: Account<'info, Auctioner>, - #[account(mut)] pub authority: Signer<'info>, + // Solver -> User SPL Token Transfer Accounts #[account(mut)] - pub user_token_in_account: Account<'info, TokenAccount>, + pub auctioner_token_in_account: Account<'info, TokenAccount>, // #[account(init_if_needed, payer = authority, associated_token::mint = token_mint, associated_token::authority = destination)] #[account(mut)] pub solver_token_in_account: Account<'info, TokenAccount>, @@ -321,7 +350,7 @@ pub struct SplTokenTransfer<'info> { pub solver_token_out_account: Account<'info, TokenAccount>, // #[account(init_if_needed, payer = authority, associated_token::mint = token_mint, associated_token::authority = destination)] #[account(mut)] - pub user_token_out_account: Account<'info, TokenAccount>, + pub auctioner_token_out_account: Account<'info, TokenAccount>, // Cross-chain Transfer Accounts @@ -354,6 +383,17 @@ pub struct SplTokenTransfer<'info> { pub system_program: Program<'info, System>, } +#[derive(Accounts)] +pub struct EscrowFunds<'info> { + #[account(mut)] + pub user: Signer<'info>, + #[account(mut)] + pub user_token_account: Account<'info, TokenAccount>, + #[account(mut)] + pub auctioner_token_account: Account<'info, TokenAccount>, + pub token_program: Program<'info, Token>, +} + // Define custom errors #[error_code] From 38d798b7688d70c2574c5a79c72d0649b01d71c2 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Fri, 9 Aug 2024 13:26:42 -0400 Subject: [PATCH 08/47] some docs and quick fixes --- .../programs/bridge-escrow/src/lib.rs | 207 ++++++++++-------- 1 file changed, 113 insertions(+), 94 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 6ea544cb..168ec5e8 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -1,6 +1,7 @@ use std::str::FromStr; use anchor_lang::prelude::*; +use anchor_lang::solana_program; use anchor_spl::associated_token::AssociatedToken; use anchor_spl::token; use anchor_spl::token::{Mint, Token, TokenAccount, Transfer as SplTransfer}; @@ -18,10 +19,12 @@ use solana_ibc::cpi::accounts::SendTransfer; use solana_ibc::cpi::send_transfer; use solana_ibc::program::SolanaIbc; use solana_ibc::storage::PrivateStorage; -use anchor_lang::solana_program; const DUMMY: &str = "0x36dd1bfe89d409f869fabbe72c3cf72ea8b460f6"; -// const BRIDGE_CONTRACT_PUBKEY: &str = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"; +// const BRIDGE_CONTRACT_PUBKEY: &str = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"; + +const AUCTIONEER_SEED: &[u8] = b"auctioneer"; +const INTENT_SEED: &[u8] = b"intent"; #[cfg(test)] mod tests; @@ -32,34 +35,35 @@ declare_id!("8t5dMbZuGsUtcX7JZpCN8kfPnt8e6VSc3XGepVTMUig4"); pub mod bridge_escrow { use super::*; - pub fn escrow_funds( - ctx: Context, - amount: u64, - ) -> Result<()> { - // Transfer SPL tokens from the user's account to the auctioner's account + pub fn initialize(ctx: Context) -> Result<()> { + // store the auctioneer + let auctioneer = &mut ctx.accounts.auctioneer; + auctioneer.authority = *ctx.accounts.authority.key; + Ok(()) + } + + /// Escrows the user funds on the source chain + /// + /// The funds are stored in token account owned by the auctioneer state PDA + pub fn escrow_funds(ctx: Context, amount: u64) -> Result<()> { + // Transfer SPL tokens from the user's account to the auctioneer's account let cpi_accounts = SplTransfer { from: ctx.accounts.user_token_account.to_account_info(), - to: ctx.accounts.auctioner_token_account.to_account_info(), + to: ctx.accounts.auctioneer_token_account.to_account_info(), authority: ctx.accounts.user.to_account_info(), }; let cpi_program = ctx.accounts.token_program.to_account_info(); let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts); - + token::transfer(cpi_ctx, amount)?; Ok(()) } - pub fn initialize( - ctx: Context, - ) -> Result<()> { - // store the auctioner - let auctioner = &mut ctx.accounts.auctioner; - auctioner.authority = *ctx.accounts.authority.key; - Ok(()) - } + + /// Called by the auctioneer whose address is stored in `auctioneer` state account. pub fn store_intent( ctx: Context, intent_id: String, @@ -70,14 +74,14 @@ pub mod bridge_escrow { amount_out: String, winner_solver: Pubkey, ) -> Result<()> { - // verify if caller is auctioner - let auctioner = &ctx.accounts.auctioner; + // verify if caller is auctioneer + let auctioneer = &ctx.accounts.auctioneer; require!( - *ctx.accounts.authority.key == auctioner.authority, + *ctx.accounts.authority.key == auctioneer.authority, ErrorCode::Unauthorized ); - // save intent on a PDA derived from the auctioner account + // save intent on a PDA derived from the auctioneer account let intent = &mut ctx.accounts.intent; intent.intent_id = intent_id; intent.user = *ctx.accounts.authority.key; @@ -93,16 +97,16 @@ pub mod bridge_escrow { // ONLY bridge contract should call this function /* - I assume this need to be done outside the Program to get the accounts + I assume this need to be done outside the Program to get the accounts - // Extract and validate the memo - let memo = msg.packet_data.memo.to_string(); - let parts: Vec<&str> = memo.split(',').collect(); - let (token_mint, amount, solver) = (parts[0], parts[1], parts[2]); + // Extract and validate the memo + let memo = msg.packet_data.memo.to_string(); + let parts: Vec<&str> = memo.split(',').collect(); + let (token_mint, amount, solver) = (parts[0], parts[1], parts[2]); - ctx.accounts.auctioner = get_token_account(token_mint, auctioner); - ctx.accounts.solver = get_token_account(token_mint, solver); - */ + ctx.accounts.auctioneer = get_token_account(token_mint, auctioneer); + ctx.accounts.solver = get_token_account(token_mint, solver); + */ pub fn on_receive_transfer( ctx: Context, msg: MsgTransfer, @@ -115,20 +119,21 @@ pub mod bridge_escrow { msg.packet_data.token.denom.base_denom.to_string() == DUMMY, ErrorCode::InvalidDenom ); - let amount: u64 = parts[1].parse().map_err(|_| ErrorCode::InvalidAmount)?; - - // Transfer tokens from Auctioner to Solver + let amount: u64 = + parts[1].parse().map_err(|_| ErrorCode::InvalidAmount)?; + + // Transfer tokens from Auctioneer to Solver let cpi_accounts = SplTransfer { - from: ctx.accounts.auctioner.to_account_info(), + from: ctx.accounts.auctioneer.to_account_info(), to: ctx.accounts.solver.to_account_info(), - authority: ctx.accounts.auctioner.to_account_info(), + authority: ctx.accounts.auctioneer.to_account_info(), }; - + let cpi_program = ctx.accounts.token_program.to_account_info(); let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts); - + token::transfer(cpi_ctx, amount)?; - + Ok(()) } @@ -137,7 +142,7 @@ pub mod bridge_escrow { ctx: Context, hashed_full_denom: CryptoHash, solver_out: String, - single_domain: bool + single_domain: bool, ) -> Result<()> { let intent = &ctx.accounts.intent; require!( @@ -150,31 +155,50 @@ pub mod bridge_escrow { // Transfer tokens from Solver to User let cpi_accounts = SplTransfer { - from: ctx.accounts.solver_token_in_account.to_account_info().clone(), - to: ctx.accounts.auctioner_token_in_account.to_account_info().clone(), + from: ctx + .accounts + .solver_token_in_account + .to_account_info() + .clone(), + to: ctx + .accounts + .auctioneer_token_in_account + .to_account_info() + .clone(), authority: authority.to_account_info().clone(), }; let cpi_program = token_program.to_account_info(); - token::transfer(CpiContext::new(cpi_program, cpi_accounts), intent.amount_in)?; + token::transfer( + CpiContext::new(cpi_program, cpi_accounts), + intent.amount_in, + )?; if single_domain { - // Transfer tokens from Auctioner to Solver + // Transfer tokens from Auctioneer to Solver let cpi_accounts = SplTransfer { - from: ctx.accounts.auctioner_token_out_account.to_account_info().clone(), - to: ctx.accounts.solver_token_out_account.to_account_info().clone(), + from: ctx + .accounts + .auctioneer_token_out_account + .to_account_info() + .clone(), + to: ctx + .accounts + .solver_token_out_account + .to_account_info() + .clone(), authority: authority.to_account_info().clone(), }; let cpi_program = token_program.to_account_info(); - token::transfer(CpiContext::new(cpi_program, cpi_accounts), intent.amount_in)?; - } - else { + token::transfer( + CpiContext::new(cpi_program, cpi_accounts), + intent.amount_in, + )?; + } else { let token_mint = ctx.accounts.token_mint.to_account_info(); let my_custom_memo = format!( "{},{},{}", - intent.token_out, - intent.amount_out, - solver_out + intent.token_out, intent.amount_out, solver_out ); // Cross-chain transfer + memo @@ -211,10 +235,11 @@ pub mod bridge_escrow { ); let memo = "{\"forward\":{\"receiver\":\"\ - 0x4c22af5da4a849a8f39be00eb1b44676ac5c9060\",\"port\":\"\ - transfer\",\"channel\":\"channel-52\",\"timeout\":\ - 600000000000000,\"next\":{\"memo\":\"my-custom-msg\"}}}" - .to_string(); + 0x4c22af5da4a849a8f39be00eb1b44676ac5c9060\",\"port\":\ + \"transfer\",\"channel\":\"channel-52\",\"timeout\":\ + 600000000000000,\"next\":{\"memo\":\"my-custom-msg\"\ + }}}" + .to_string(); let memo = memo.replace("my-custom-msg", &my_custom_memo); // MsgTransfer @@ -235,7 +260,9 @@ pub mod bridge_escrow { receiver: String::from("pfm").into(), memo: memo.into(), }, - timeout_height_on_b: At(Height::new(2018502000, 29340670).unwrap()), + timeout_height_on_b: At( + Height::new(2018502000, 29340670).unwrap() + ), timeout_timestamp_on_b: Timestamp::from_nanoseconds( 1000000000000000000, ) @@ -249,51 +276,42 @@ pub mod bridge_escrow { let intent_account_info = &mut ctx.accounts.intent.to_account_info(); **intent_account_info.try_borrow_mut_lamports()? = 0; intent_account_info.data.borrow_mut().fill(0); - + Ok(()) } - } -// Define the Auctioner account +// Define the Auctioneer account #[account] -pub struct Auctioner { +pub struct Auctioneer { pub authority: Pubkey, } // Define the Intent account with space calculation #[account] +#[derive(InitSpace)] pub struct Intent { + #[max_len(20)] pub intent_id: String, pub user: Pubkey, pub user_in: Pubkey, pub token_in: Pubkey, pub amount_in: u64, - pub token_out: String, // 20 bytes - pub amount_out: String, // 20 bytes + #[max_len(20)] + pub token_out: String, + #[max_len(20)] + pub amount_out: String, pub winner_solver: Pubkey, } -impl Intent { - pub const LEN: usize = 8 // discriminator - + 4 + 8 // intent_id: String (assuming a max length of 8 bytes) - + 32 // user: Pubkey - + 32 // user_in: Pubkey - + 32 // token_in: Pubkey - + 8 // amount_in: u64 - + 4 + 20 // token_out: String (assuming a max length of 20 bytes) - + 4 + 20 // amount_out: String (assuming a max length of 20 bytes) - + 32; // winner_solver: Pubkey -} - // Define the context for initializing the program #[derive(Accounts)] #[instruction()] pub struct Initialize<'info> { - #[account(init, seeds = [b"auctioner"], bump, payer = authority, space = 8 + 32)] - pub auctioner: Account<'info, Auctioner>, #[account(mut)] pub authority: Signer<'info>, + #[account(init, seeds = [AUCTIONEER_SEED], bump, payer = authority, space = 8 + 32)] + pub auctioneer: Account<'info, Auctioneer>, pub system_program: Program<'info, System>, } @@ -301,25 +319,25 @@ pub struct Initialize<'info> { #[derive(Accounts)] #[instruction(intent_id: String)] pub struct StoreIntent<'info> { - #[account(init_if_needed, seeds = [b"intent", intent_id.as_bytes()], bump, payer = authority, space = Intent::LEN)] - pub intent: Account<'info, Intent>, - #[account(seeds = [b"auctioner"], bump)] - pub auctioner: Account<'info, Auctioner>, #[account(mut)] pub authority: Signer<'info>, + #[account(init, seeds = [INTENT_SEED, intent_id.as_bytes()], bump, payer = authority, space = Intent::INIT_SPACE)] + pub intent: Account<'info, Intent>, + #[account(seeds = [AUCTIONEER_SEED], bump)] + pub auctioneer: Account<'info, Auctioneer>, pub system_program: Program<'info, System>, } #[derive(Accounts)] pub struct ReceiveTransferContext<'info> { - #[account(seeds = [b"auctioner"], bump)] - pub auctioner: Account<'info, Auctioner>, #[account(mut)] pub solver: Signer<'info>, + #[account(seeds = [AUCTIONEER_SEED], bump)] + pub auctioneer: Account<'info, Auctioneer>, #[account(address = solana_program::sysvar::instructions::ID)] /// CHECK: Used for getting the caller program id to verify if the right /// program is calling the method. - instruction: UncheckedAccount<'info>, + pub instruction: UncheckedAccount<'info>, pub token_program: Program<'info, Token>, #[account(mut)] pub token_account: Account<'info, TokenAccount>, @@ -330,28 +348,26 @@ pub struct ReceiveTransferContext<'info> { #[instruction(intent_id: String)] pub struct SplTokenTransfer<'info> { // Intent reading - #[account(seeds = [b"intent", intent_id.as_bytes()], bump)] + #[account(seeds = [INTENT_SEED, intent_id.as_bytes()], bump)] pub intent: Account<'info, Intent>, - #[account(seeds = [b"auctioner"], bump)] - pub auctioner: Account<'info, Auctioner>, + #[account(seeds = [AUCTIONEER_SEED], bump)] + pub auctioneer: Account<'info, Auctioneer>, #[account(mut)] pub authority: Signer<'info>, // Solver -> User SPL Token Transfer Accounts #[account(mut)] - pub auctioner_token_in_account: Account<'info, TokenAccount>, + pub auctioneer_token_in_account: Account<'info, TokenAccount>, // #[account(init_if_needed, payer = authority, associated_token::mint = token_mint, associated_token::authority = destination)] #[account(mut)] pub solver_token_in_account: Account<'info, TokenAccount>, - // User -> Solver SPL Token Transfer Accounts #[account(mut)] pub solver_token_out_account: Account<'info, TokenAccount>, // #[account(init_if_needed, payer = authority, associated_token::mint = token_mint, associated_token::authority = destination)] #[account(mut)] - pub auctioner_token_out_account: Account<'info, TokenAccount>, - + pub auctioneer_token_out_account: Account<'info, TokenAccount>, // Cross-chain Transfer Accounts pub ibc_program: Program<'info, SolanaIbc>, // Use IbcProgram here @@ -387,11 +403,16 @@ pub struct SplTokenTransfer<'info> { pub struct EscrowFunds<'info> { #[account(mut)] pub user: Signer<'info>, - #[account(mut)] + #[account(mut, token::authority = user, token::mint = token_mint)] pub user_token_account: Account<'info, TokenAccount>, - #[account(mut)] - pub auctioner_token_account: Account<'info, TokenAccount>, + #[account(seeds = [AUCTIONEER_SEED], bump)] + pub auctioneer_state: Account<'info, Auctioneer>, + pub token_mint: Account<'info, Mint>, + #[account(init_if_needed, payer = user, associated_token::mint = token_mint, associated_token::authority = auctioneer_state)] + pub auctioneer_token_account: Account<'info, TokenAccount>, pub token_program: Program<'info, Token>, + pub associated_token_program: Program<'info, AssociatedToken>, + pub system_program: Program<'info, System>, } @@ -413,5 +434,3 @@ pub enum ErrorCode { #[msg("Denom is not DUMMY token")] InvalidDenom, } - - From 35c58ee6790091bf30ad10d0b9b7dd7efb988202 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Mon, 12 Aug 2024 07:44:56 -0400 Subject: [PATCH 09/47] add timeout method --- .../programs/bridge-escrow/src/lib.rs | 78 +++++++++++++++++-- 1 file changed, 71 insertions(+), 7 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 168ec5e8..a0c21347 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -49,7 +49,7 @@ pub mod bridge_escrow { // Transfer SPL tokens from the user's account to the auctioneer's account let cpi_accounts = SplTransfer { from: ctx.accounts.user_token_account.to_account_info(), - to: ctx.accounts.auctioneer_token_account.to_account_info(), + to: ctx.accounts.escrow_token_account.to_account_info(), authority: ctx.accounts.user.to_account_info(), }; @@ -72,6 +72,7 @@ pub mod bridge_escrow { amount_in: u64, token_out: String, amount_out: String, + timeout_in_sec: u64, winner_solver: Pubkey, ) -> Result<()> { // verify if caller is auctioneer @@ -80,15 +81,17 @@ pub mod bridge_escrow { *ctx.accounts.authority.key == auctioneer.authority, ErrorCode::Unauthorized ); + let current_timestamp = Clock::get()?.unix_timestamp as u64; + require!(timeout_in_sec > current_timestamp, ErrorCode::InvalidTimeout); // save intent on a PDA derived from the auctioneer account let intent = &mut ctx.accounts.intent; intent.intent_id = intent_id; - intent.user = *ctx.accounts.authority.key; - intent.user_in = user_in; + intent.user = user_in; intent.token_in = token_in; intent.amount_in = amount_in; intent.token_out = token_out; + intent.timeout_timestamp_in_sec = timeout_in_sec; intent.amount_out = amount_out; intent.winner_solver = winner_solver; @@ -109,7 +112,7 @@ pub mod bridge_escrow { */ pub fn on_receive_transfer( ctx: Context, - msg: MsgTransfer, + intent_id: String, ) -> Result<()> { // Extract and validate the memo let memo = msg.packet_data.memo.to_string(); @@ -279,6 +282,35 @@ pub mod bridge_escrow { Ok(()) } + + /// If the intent has not been solved, then the funds can withdrawn by the user + /// after the timeout period has passed. + pub fn on_timeout(ctx: Context, _intent_id: String) -> Result<()> { + let authority = &ctx.accounts.user.key(); + + let intent = &ctx.accounts.intent; + require!(authority == &intent.user, ErrorCode::Unauthorized); + + let current_time = Clock::get()?.unix_timestamp as u64; + require!(current_time >= intent.timeout_timestamp_in_sec, ErrorCode::IntentNotTimedOut); + + let bump = ctx.bumps.auctioneer_state; + let signer_seeds = &[AUCTIONEER_SEED, &[bump]]; + let signer_seeds = signer_seeds.as_ref(); + let signer_seeds = core::slice::from_ref(&signer_seeds); + + // Unescrow the tokens + let cpi_accounts = SplTransfer { + from: ctx.accounts.escrow_token_account.to_account_info(), + to: ctx.accounts.user_token_account.to_account_info(), + authority: ctx.accounts.auctioneer_state.to_account_info(), + }; + + let cpi_ctx = CpiContext::new_with_signer(ctx.accounts.token_program.to_account_info(), cpi_accounts, signer_seeds); + anchor_spl::token::transfer(cpi_ctx, intent.amount_in)?; + + Ok(()) + } } // Define the Auctioneer account @@ -294,7 +326,6 @@ pub struct Intent { #[max_len(20)] pub intent_id: String, pub user: Pubkey, - pub user_in: Pubkey, pub token_in: Pubkey, pub amount_in: u64, #[max_len(20)] @@ -302,6 +333,9 @@ pub struct Intent { #[max_len(20)] pub amount_out: String, pub winner_solver: Pubkey, + // Timestamp when the intent was created + pub creation_timestamp_in_sec: u64, + pub timeout_timestamp_in_sec: u64, } // Define the context for initializing the program @@ -329,11 +363,16 @@ pub struct StoreIntent<'info> { } #[derive(Accounts)] +#[instruction(intent_id: String)] pub struct ReceiveTransferContext<'info> { #[account(mut)] pub solver: Signer<'info>, #[account(seeds = [AUCTIONEER_SEED], bump)] - pub auctioneer: Account<'info, Auctioneer>, + pub auctioneer_state: Account<'info, Auctioneer>, + /// CHECK: + pub auctioneer: UncheckedAccount<'info>, + #[account(mut, close = auctioneer, seeds = [INTENT_SEED, intent_id.as_bytes()], bump)] + pub intent: Account<'info, Intent>, #[account(address = solana_program::sysvar::instructions::ID)] /// CHECK: Used for getting the caller program id to verify if the right /// program is calling the method. @@ -409,12 +448,33 @@ pub struct EscrowFunds<'info> { pub auctioneer_state: Account<'info, Auctioneer>, pub token_mint: Account<'info, Mint>, #[account(init_if_needed, payer = user, associated_token::mint = token_mint, associated_token::authority = auctioneer_state)] - pub auctioneer_token_account: Account<'info, TokenAccount>, + pub escrow_token_account: Account<'info, TokenAccount>, pub token_program: Program<'info, Token>, pub associated_token_program: Program<'info, AssociatedToken>, pub system_program: Program<'info, System>, } +#[derive(Accounts)] +#[instruction(intent_id: String)] +pub struct OnTimeout<'info> { + #[account(mut)] + pub user: Signer<'info>, + #[account(mut, token::authority = user, token::mint = token_mint)] + pub user_token_account: Account<'info, TokenAccount>, + #[account(seeds = [AUCTIONEER_SEED], bump, constraint = auctioneer_state.authority == *auctioneer.key)] + pub auctioneer_state: Account<'info, Auctioneer>, + #[account(mut)] + /// CHECK: + pub auctioneer: UncheckedAccount<'info>, + #[account(mut, close = auctioneer, seeds = [INTENT_SEED, intent_id.as_bytes()], bump)] + pub intent: Account<'info, Intent>, + pub token_mint: Account<'info, Mint>, + #[account(mut, token::mint = token_mint, token::authority = auctioneer_state)] + pub escrow_token_account: Account<'info, TokenAccount>, + pub token_program: Program<'info, Token>, + pub system_program: Program<'info, System>, +} + // Define custom errors #[error_code] @@ -433,4 +493,8 @@ pub enum ErrorCode { TransferFailed, #[msg("Denom is not DUMMY token")] InvalidDenom, + #[msg("Timeout is lesser than the current time")] + InvalidTimeout, + #[msg("Intent hasnt timed out yet")] + IntentNotTimedOut, } From 1d7e0d7837ce8ba6395ff42f37c403c00e06fd54 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Mon, 12 Aug 2024 07:45:54 -0400 Subject: [PATCH 10/47] fix receive method argument --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index a0c21347..748409a4 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -112,7 +112,7 @@ pub mod bridge_escrow { */ pub fn on_receive_transfer( ctx: Context, - intent_id: String, + msg: MsgTransfer, ) -> Result<()> { // Extract and validate the memo let memo = msg.packet_data.memo.to_string(); From a308799d8f2402b93c21c79bb016264f31a1f822 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Wed, 14 Aug 2024 04:58:17 +0530 Subject: [PATCH 11/47] added tests for single domain --- Anchor.toml | 8 +- solana-test.sh | 26 +- .../programs/bridge-escrow/src/lib.rs | 237 +++++++----- .../programs/bridge-escrow/src/tests.rs | 361 ++++++++++++++---- .../restaking/programs/restaking/src/lib.rs | 2 +- .../solana-ibc/programs/solana-ibc/src/lib.rs | 2 +- 6 files changed, 450 insertions(+), 186 deletions(-) diff --git a/Anchor.toml b/Anchor.toml index e82664d1..ae54b40d 100644 --- a/Anchor.toml +++ b/Anchor.toml @@ -6,13 +6,13 @@ skip-lint = false [programs.devnet] bridge-escrow = "A5ygmioT2hWFnxpPapY3XyDjwwfMDhnSP1Yxoynd5hs4" -restaking = "9JkWjSfc5Yb5EdTwhxHDx6rh8usXYVFm9KFwqzskVE8t" -solana_ibc = "3JvDhxt87SqKwNSuBPWWSRsfSxzkjzofDh1B6DioqfQ3" +restaking = "8n3FHwYxFgQCQc2FNFkwDUf9mcqupxXcCvgfHbApMLv3" +solana_ibc = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT" [programs.localnet] bridge-escrow = "A5ygmioT2hWFnxpPapY3XyDjwwfMDhnSP1Yxoynd5hs4" -restaking = "9JkWjSfc5Yb5EdTwhxHDx6rh8usXYVFm9KFwqzskVE8t" -solana_ibc = "3JvDhxt87SqKwNSuBPWWSRsfSxzkjzofDh1B6DioqfQ3" +restaking = "8n3FHwYxFgQCQc2FNFkwDUf9mcqupxXcCvgfHbApMLv3" +solana_ibc = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT" [registry] url = "https://api.apr.dev" diff --git a/solana-test.sh b/solana-test.sh index 629a12c4..3f33b9f4 100755 --- a/solana-test.sh +++ b/solana-test.sh @@ -1,15 +1,15 @@ #!/bin/sh -set -eux -solana config set --url http://127.0.0.1:8899 -cd solana/write-account -cargo build-sbf -cd ../.. -cd solana/signature-verifier -cargo build-sbf -cd ../.. -solana program deploy target/deploy/write.so -solana program deploy target/deploy/sigverify.so -cargo test --lib -- --nocapture --include-ignored ::anchor +# set -eux +# solana config set --url http://127.0.0.1:8899 +# cd solana/write-account +# cargo build-sbf +# cd ../.. +# cd solana/signature-verifier +# cargo build-sbf +# cd ../.. +# solana program deploy target/deploy/write.so +# solana program deploy target/deploy/sigverify.so +# cargo test --lib -- --nocapture --include-ignored ::anchor cargo test --lib -- --nocapture --include-ignored ::escrow -find solana/restaking/tests/ -name '*.ts' \ - -exec yarn run ts-mocha -p ./tsconfig.json -t 1000000 {} + +# find solana/restaking/tests/ -name '*.ts' \ +# -exec yarn run ts-mocha -p ./tsconfig.json -t 1000000 {} + diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 748409a4..d81e14fc 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -29,7 +29,7 @@ const INTENT_SEED: &[u8] = b"intent"; #[cfg(test)] mod tests; -declare_id!("8t5dMbZuGsUtcX7JZpCN8kfPnt8e6VSc3XGepVTMUig4"); +declare_id!("43VAmkAMHhRMX124zHZiQDk9SwbXqhZaWDvGrfeo4eHv"); #[program] pub mod bridge_escrow { @@ -61,8 +61,6 @@ pub mod bridge_escrow { Ok(()) } - - /// Called by the auctioneer whose address is stored in `auctioneer` state account. pub fn store_intent( ctx: Context, @@ -81,8 +79,6 @@ pub mod bridge_escrow { *ctx.accounts.authority.key == auctioneer.authority, ErrorCode::Unauthorized ); - let current_timestamp = Clock::get()?.unix_timestamp as u64; - require!(timeout_in_sec > current_timestamp, ErrorCode::InvalidTimeout); // save intent on a PDA derived from the auctioneer account let intent = &mut ctx.accounts.intent; @@ -143,32 +139,29 @@ pub mod bridge_escrow { // this function is called by Solver pub fn send_funds_to_user( ctx: Context, - hashed_full_denom: CryptoHash, - solver_out: String, + intent_id: String, + hashed_full_denom: Option, + solver_out: Option, single_domain: bool, ) -> Result<()> { let intent = &ctx.accounts.intent; require!( - *ctx.accounts.authority.key == intent.winner_solver, + *ctx.accounts.solver.key == intent.winner_solver, ErrorCode::Unauthorized ); let token_program = &ctx.accounts.token_program; - let authority = &ctx.accounts.authority; + let solver = &ctx.accounts.solver; // Transfer tokens from Solver to User let cpi_accounts = SplTransfer { from: ctx .accounts - .solver_token_in_account + .solver_token_out_account .to_account_info() .clone(), - to: ctx - .accounts - .auctioneer_token_in_account - .to_account_info() - .clone(), - authority: authority.to_account_info().clone(), + to: ctx.accounts.user_token_out_account.to_account_info().clone(), + authority: solver.to_account_info().clone(), }; let cpi_program = token_program.to_account_info(); token::transfer( @@ -178,26 +171,41 @@ pub mod bridge_escrow { if single_domain { // Transfer tokens from Auctioneer to Solver + + let bump = ctx.bumps.auctioneer_state; + let seeds = + &[AUCTIONEER_SEED.as_ref(), core::slice::from_ref(&bump)]; + let seeds = seeds.as_ref(); + let signer_seeds = core::slice::from_ref(&seeds); + let cpi_accounts = SplTransfer { from: ctx .accounts - .auctioneer_token_out_account - .to_account_info() - .clone(), - to: ctx - .accounts - .solver_token_out_account - .to_account_info() - .clone(), - authority: authority.to_account_info().clone(), + .auctioneer_token_in_account + .to_account_info(), + to: ctx.accounts.solver_token_in_account.to_account_info(), + authority: ctx.accounts.auctioneer_state.to_account_info(), }; let cpi_program = token_program.to_account_info(); token::transfer( - CpiContext::new(cpi_program, cpi_accounts), + CpiContext::new_with_signer( + cpi_program, + cpi_accounts, + signer_seeds, + ), intent.amount_in, )?; } else { - let token_mint = ctx.accounts.token_mint.to_account_info(); + let solver_out = + solver_out.ok_or(ErrorCode::InvalidSolverAddress)?; + let hashed_full_denom = + hashed_full_denom.ok_or(ErrorCode::InvalidTokenAddress)?; + + let token_mint = ctx + .accounts + .token_mint + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)?; let my_custom_memo = format!( "{},{},{}", @@ -206,34 +214,68 @@ pub mod bridge_escrow { // Cross-chain transfer + memo let transfer_ctx = CpiContext::new( - ctx.accounts.ibc_program.to_account_info().clone(), + ctx.accounts + .ibc_program + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), SendTransfer { - sender: authority.to_account_info().clone(), - receiver: Some(ctx.accounts.receiver.to_account_info()), - storage: ctx.accounts.storage.to_account_info().clone(), - trie: ctx.accounts.trie.to_account_info().clone(), - chain: ctx.accounts.chain.to_account_info().clone(), - mint_authority: Some( - ctx.accounts.mint_authority.to_account_info(), - ), - token_mint: Some(ctx.accounts.token_mint.to_account_info()), - escrow_account: Some( - ctx.accounts.escrow_account.to_account_info(), - ), - receiver_token_account: Some( - ctx.accounts.receiver_token_account.to_account_info(), - ), - fee_collector: Some( - ctx.accounts.fee_collector.to_account_info(), - ), + sender: solver.to_account_info(), + receiver: ctx + .accounts + .receiver + .as_ref() + .and_then(|acc| Some(acc.to_account_info())), + storage: ctx + .accounts + .storage + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), + trie: ctx + .accounts + .trie + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), + chain: ctx + .accounts + .chain + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), + mint_authority: ctx + .accounts + .mint_authority + .as_ref() + .and_then(|acc| Some(acc.to_account_info())), + token_mint: ctx + .accounts + .token_mint + .as_ref() + .and_then(|acc| Some(acc.to_account_info())), + escrow_account: ctx + .accounts + .escrow_account + .as_ref() + .and_then(|acc| Some(acc.to_account_info())), + receiver_token_account: ctx + .accounts + .receiver_token_account + .as_ref() + .and_then(|acc| Some(acc.to_account_info())), + fee_collector: ctx + .accounts + .fee_collector + .as_ref() + .and_then(|acc| Some(acc.to_account_info())), token_program: Some( - ctx.accounts.token_program.to_account_info().clone(), + ctx.accounts.token_program.to_account_info(), ), system_program: ctx .accounts .system_program - .to_account_info() - .clone(), + .to_account_info(), }, ); @@ -258,7 +300,7 @@ pub mod bridge_escrow { amount: 1.into(), }, sender: IbcSigner::from( - ctx.accounts.authority.key().to_string(), + ctx.accounts.solver.key().to_string(), ), receiver: String::from("pfm").into(), memo: memo.into(), @@ -275,24 +317,30 @@ pub mod bridge_escrow { send_transfer(transfer_ctx, hashed_full_denom, msg)?; } - // Delete intent by closing the account - let intent_account_info = &mut ctx.accounts.intent.to_account_info(); - **intent_account_info.try_borrow_mut_lamports()? = 0; - intent_account_info.data.borrow_mut().fill(0); + // // Delete intent by closing the account + // let intent_account_info = &mut ctx.accounts.intent.to_account_info(); + // **intent_account_info.try_borrow_mut_lamports()? = 0; + // intent_account_info.data.borrow_mut().fill(0); Ok(()) } /// If the intent has not been solved, then the funds can withdrawn by the user /// after the timeout period has passed. - pub fn on_timeout(ctx: Context, _intent_id: String) -> Result<()> { - let authority = &ctx.accounts.user.key(); + pub fn on_timeout( + ctx: Context, + _intent_id: String, + ) -> Result<()> { + let authority = &ctx.accounts.user.key(); let intent = &ctx.accounts.intent; - require!(authority == &intent.user, ErrorCode::Unauthorized); + require!(authority == &intent.user, ErrorCode::Unauthorized); let current_time = Clock::get()?.unix_timestamp as u64; - require!(current_time >= intent.timeout_timestamp_in_sec, ErrorCode::IntentNotTimedOut); + require!( + current_time >= intent.timeout_timestamp_in_sec, + ErrorCode::IntentNotTimedOut + ); let bump = ctx.bumps.auctioneer_state; let signer_seeds = &[AUCTIONEER_SEED, &[bump]]; @@ -306,7 +354,11 @@ pub mod bridge_escrow { authority: ctx.accounts.auctioneer_state.to_account_info(), }; - let cpi_ctx = CpiContext::new_with_signer(ctx.accounts.token_program.to_account_info(), cpi_accounts, signer_seeds); + let cpi_ctx = CpiContext::new_with_signer( + ctx.accounts.token_program.to_account_info(), + cpi_accounts, + signer_seeds, + ); anchor_spl::token::transfer(cpi_ctx, intent.amount_in)?; Ok(()) @@ -355,7 +407,7 @@ pub struct Initialize<'info> { pub struct StoreIntent<'info> { #[account(mut)] pub authority: Signer<'info>, - #[account(init, seeds = [INTENT_SEED, intent_id.as_bytes()], bump, payer = authority, space = Intent::INIT_SPACE)] + #[account(init, seeds = [INTENT_SEED, intent_id.as_bytes()], bump, payer = authority, space = 8 + Intent::INIT_SPACE)] pub intent: Account<'info, Intent>, #[account(seeds = [AUCTIONEER_SEED], bump)] pub auctioneer: Account<'info, Auctioneer>, @@ -387,55 +439,63 @@ pub struct ReceiveTransferContext<'info> { #[instruction(intent_id: String)] pub struct SplTokenTransfer<'info> { // Intent reading - #[account(seeds = [INTENT_SEED, intent_id.as_bytes()], bump)] + #[account(mut, close = auctioneer, seeds = [INTENT_SEED, intent_id.as_bytes()], bump)] pub intent: Account<'info, Intent>, #[account(seeds = [AUCTIONEER_SEED], bump)] - pub auctioneer: Account<'info, Auctioneer>, + pub auctioneer_state: Account<'info, Auctioneer>, #[account(mut)] - pub authority: Signer<'info>, + pub solver: Signer<'info>, - // Solver -> User SPL Token Transfer Accounts - #[account(mut)] + #[account(mut, address = auctioneer_state.authority)] + /// CHECK: + pub auctioneer: UncheckedAccount<'info>, + + pub token_in: Account<'info, Mint>, + pub token_out: Account<'info, Mint>, + + // Program (Escrow) -> Solver SPL Token Transfer Accounts + #[account(mut, token::mint = token_in, token::authority = auctioneer_state)] pub auctioneer_token_in_account: Account<'info, TokenAccount>, - // #[account(init_if_needed, payer = authority, associated_token::mint = token_mint, associated_token::authority = destination)] - #[account(mut)] + #[account(mut, token::authority = solver, token::mint = token_in)] pub solver_token_in_account: Account<'info, TokenAccount>, - // User -> Solver SPL Token Transfer Accounts - #[account(mut)] + // Solver -> User SPL Token Transfer Accounts + #[account(mut, token::authority = solver, token::mint = token_out)] pub solver_token_out_account: Account<'info, TokenAccount>, - // #[account(init_if_needed, payer = authority, associated_token::mint = token_mint, associated_token::authority = destination)] - #[account(mut)] - pub auctioneer_token_out_account: Account<'info, TokenAccount>, + #[account(mut, token::mint = token_out)] + pub user_token_out_account: Account<'info, TokenAccount>, + + pub token_program: Program<'info, Token>, + pub associated_token_program: Program<'info, AssociatedToken>, + pub system_program: Program<'info, System>, + + // The accounts below are only needed for cross chain intents // Cross-chain Transfer Accounts - pub ibc_program: Program<'info, SolanaIbc>, // Use IbcProgram here + pub ibc_program: Option>, // Use IbcProgram here #[account(mut)] /// CHECK: - pub receiver: AccountInfo<'info>, + pub receiver: Option>, #[account(mut)] - pub storage: Account<'info, PrivateStorage>, + pub storage: Option>, /// CHECK: #[account(mut)] - pub trie: UncheckedAccount<'info>, + pub trie: Option>, #[account(mut)] - pub chain: Box>, + pub chain: Option>>, /// CHECK: #[account(mut)] - pub mint_authority: UncheckedAccount<'info>, + pub mint_authority: Option>, #[account(mut)] - pub token_mint: Box>, + pub token_mint: Option>>, /// CHECK: #[account(mut)] - pub escrow_account: UncheckedAccount<'info>, + pub escrow_account: Option>, #[account(mut)] - pub receiver_token_account: Box>, + pub receiver_token_account: Option>>, /// CHECK: #[account(mut)] - pub fee_collector: UncheckedAccount<'info>, - pub token_program: Program<'info, Token>, - pub associated_token_program: Program<'info, AssociatedToken>, - pub system_program: Program<'info, System>, + pub fee_collector: Option>, } #[derive(Accounts)] @@ -475,7 +535,6 @@ pub struct OnTimeout<'info> { pub system_program: Program<'info, System>, } - // Define custom errors #[error_code] pub enum ErrorCode { @@ -497,4 +556,10 @@ pub enum ErrorCode { InvalidTimeout, #[msg("Intent hasnt timed out yet")] IntentNotTimedOut, + #[msg("Solana ibc accounts not present")] + AccountsNotPresent, + #[msg("Invalid solver out address")] + InvalidSolverOutAddress, + #[msg("Invalid hashed full denom")] + InvalidHashedFullDenom, } diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index 2da24769..5c942c3e 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -12,13 +12,15 @@ use anchor_client::solana_sdk::signature::{ Keypair, Signature, Signer as SolanaSigner, }; use anchor_client::{Client, Cluster}; -use anchor_spl::associated_token::get_associated_token_address; +use anchor_lang::system_program; +use anchor_spl::associated_token::{self, get_associated_token_address}; use anyhow::Result; use ibc::apps::transfer::types::{PrefixedCoin, PrefixedDenom}; use spl_token::instruction::initialize_mint2; use spl_token::solana_program::system_instruction::create_account; const MINT_AMOUNT: u64 = 1_000_000_000; +const TRANSFER_AMOUNT: u64 = 1_000_000; fn airdrop(client: &RpcClient, account: Pubkey, lamports: u64) -> Signature { let balance_before = client.get_balance(&account).unwrap(); @@ -37,78 +39,81 @@ fn airdrop(client: &RpcClient, account: Pubkey, lamports: u64) -> Signature { #[ignore = "Requires local validator to run"] fn escrow_bridge_program() -> Result<()> { // Setup the client and wallet - let payer = Rc::new(Keypair::new()); + let user = Rc::new(Keypair::new()); let client = Client::new_with_options( Cluster::Localnet, - payer.clone(), + user.clone(), CommitmentConfig::processed(), ); let program = client.program(crate::ID)?; let sol_rpc_client = program.rpc(); - let authority = Rc::new(Keypair::new()); let lamports = 2_000_000_000; - let receiver = Rc::new(Keypair::new()); - let mint_keypair = Keypair::new(); - let native_token_mint_key = mint_keypair.pubkey(); + let solver = Rc::new(Keypair::new()); + let auctioneer = Rc::new(Keypair::new()); + let token_in_keypair = Keypair::new(); + let token_in = token_in_keypair.pubkey(); + let token_out_keypair = Keypair::new(); + let token_out = token_out_keypair.pubkey(); let program_rpc = program.rpc(); - airdrop(&program_rpc, authority.pubkey(), lamports); - // airdrop(&program_rpc, fee_collector, lamports); - airdrop(&program_rpc, receiver.pubkey(), lamports); + airdrop(&program_rpc, auctioneer.pubkey(), lamports); + airdrop(&program_rpc, user.pubkey(), lamports); + airdrop(&program_rpc, solver.pubkey(), lamports); + + let auctioneer_state = + Pubkey::find_program_address(&[crate::AUCTIONEER_SEED], &crate::ID).0; /* - * Creating Token Mint + * Creating Token In Mint */ - println!("\nCreating a token mint"); + println!("\nCreating a token in mint"); - let create_account_ix = create_account( - &authority.pubkey(), - &native_token_mint_key, + let create_token_in_account_ix = create_account( + &auctioneer.pubkey(), + &token_in, sol_rpc_client.get_minimum_balance_for_rent_exemption(82).unwrap(), 82, &anchor_spl::token::ID, ); - let create_mint_ix = initialize_mint2( + let create_token_in_mint_ix = initialize_mint2( &anchor_spl::token::ID, - &native_token_mint_key, - &authority.pubkey(), - Some(&authority.pubkey()), + &token_in, + &auctioneer.pubkey(), + Some(&auctioneer.pubkey()), 6, ) .expect("invalid mint instruction"); - let create_token_acc_ix = spl_associated_token_account::instruction::create_associated_token_account(&authority.pubkey(), &authority.pubkey(), &native_token_mint_key, &anchor_spl::token::ID); - let create_token_acc_ix_2 = spl_associated_token_account::instruction::create_associated_token_account(&authority.pubkey(), &receiver.pubkey(), &native_token_mint_key, &anchor_spl::token::ID); - let associated_token_addr = get_associated_token_address( - &authority.pubkey(), - &native_token_mint_key, - ); + let create_token_acc_ix = spl_associated_token_account::instruction::create_associated_token_account(&auctioneer.pubkey(), &solver.pubkey(), &token_in, &anchor_spl::token::ID); + let create_token_acc_ix_2 = spl_associated_token_account::instruction::create_associated_token_account(&auctioneer.pubkey(), &user.pubkey(), &token_in, &anchor_spl::token::ID); + let user_token_in_addr = + get_associated_token_address(&user.pubkey(), &token_in); let mint_ix = spl_token::instruction::mint_to( &anchor_spl::token::ID, - &native_token_mint_key, - &associated_token_addr, - &authority.pubkey(), - &[&authority.pubkey()], + &token_in, + &user_token_in_addr, + &auctioneer.pubkey(), + &[&auctioneer.pubkey()], MINT_AMOUNT, ) .unwrap(); let tx = program .request() - .instruction(create_account_ix) - .instruction(create_mint_ix) + .instruction(create_token_in_account_ix) + .instruction(create_token_in_mint_ix) .instruction(create_token_acc_ix) .instruction(create_token_acc_ix_2) .instruction(mint_ix) - .payer(authority.clone()) - .signer(&*authority) - .signer(&mint_keypair) + .payer(auctioneer.clone()) + .signer(&*auctioneer) + .signer(&token_in_keypair) .send_with_spinner_and_config(RpcSendTransactionConfig { skip_preflight: true, ..RpcSendTransactionConfig::default() @@ -116,63 +121,252 @@ fn escrow_bridge_program() -> Result<()> { println!(" Signature: {}", tx); - let hashed_full_denom = lib::hash::CryptoHash::digest( - &native_token_mint_key.to_string().as_bytes(), + /* + * Creating Token Out Mint + */ + println!("\nCreating a token out mint"); + + let create_token_out_account_ix = create_account( + &auctioneer.pubkey(), + &token_out, + sol_rpc_client.get_minimum_balance_for_rent_exemption(82).unwrap(), + 82, + &anchor_spl::token::ID, ); - println!("Native token mint {}", native_token_mint_key); - println!("hashed full denom {}", hashed_full_denom); + let create_token_out_mint_ix = initialize_mint2( + &anchor_spl::token::ID, + &token_out, + &auctioneer.pubkey(), + Some(&auctioneer.pubkey()), + 6, + ) + .expect("invalid mint instruction"); - let x = PrefixedCoin { - denom: PrefixedDenom::from_str(&native_token_mint_key.to_string()) - .unwrap(), // token only owned by this PDA - amount: 1.into(), - }; + let create_token_acc_ix = spl_associated_token_account::instruction::create_associated_token_account(&auctioneer.pubkey(), &solver.pubkey(), &token_out, &anchor_spl::token::ID); + let create_token_acc_ix_2 = spl_associated_token_account::instruction::create_associated_token_account(&auctioneer.pubkey(), &user.pubkey(), &token_out, &anchor_spl::token::ID); + let solver_token_out_addr = + get_associated_token_address(&solver.pubkey(), &token_out); + let mint_ix = spl_token::instruction::mint_to( + &anchor_spl::token::ID, + &token_out, + &solver_token_out_addr, + &auctioneer.pubkey(), + &[&auctioneer.pubkey()], + MINT_AMOUNT, + ) + .unwrap(); - println!("full denom {:?}", x.denom.to_string()); - println!( - "hashed full denom {:?}", - lib::hash::CryptoHash::digest(x.denom.to_string().as_bytes()) - ); + let tx = program + .request() + .instruction(create_token_out_account_ix) + .instruction(create_token_out_mint_ix) + .instruction(create_token_acc_ix) + .instruction(create_token_acc_ix_2) + .instruction(mint_ix) + .payer(auctioneer.clone()) + .signer(&*auctioneer) + .signer(&token_out_keypair) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..RpcSendTransactionConfig::default() + })?; - // Derive the necessary accounts - let (storage, _bump_storage) = Pubkey::find_program_address( - &[solana_ibc::SOLANA_IBC_STORAGE_SEED], - &solana_ibc::ID, - ); - let (trie, _bump_trie) = - Pubkey::find_program_address(&[solana_ibc::TRIE_SEED], &solana_ibc::ID); - let (chain, _bump_chain) = Pubkey::find_program_address( - &[solana_ibc::CHAIN_SEED], - &solana_ibc::ID, - ); - let (mint_authority, _bump_mint_authority) = Pubkey::find_program_address( - &[solana_ibc::MINT_ESCROW_SEED], - &solana_ibc::ID, - ); - let (escrow_account, _bump_escrow_account) = Pubkey::find_program_address( - &[solana_ibc::ESCROW, &hashed_full_denom.as_slice()], - &solana_ibc::ID, - ); + println!(" Signature: {}", tx); - let receiver_token_account = get_associated_token_address( - &authority.pubkey(), - &native_token_mint_key, - ); - let (fee_collector, _bump_fee_collector) = - Pubkey::find_program_address(&[solana_ibc::FEE_SEED], &solana_ibc::ID); + // let hashed_full_denom = lib::hash::CryptoHash::digest( + // &native_token_mint_key.to_string().as_bytes(), + // ); - let system_program = anchor_lang::system_program::ID; + // println!("Native token mint {}", native_token_mint_key); + // println!("hashed full denom {}", hashed_full_denom); - // Amount to transfer - let amount = 1000000; // Example amount + // let x = PrefixedCoin { + // denom: PrefixedDenom::from_str(&native_token_mint_key.to_string()) + // .unwrap(), // token only owned by this PDA + // amount: 1.into(), + // }; - let destination_token_account = get_associated_token_address( - &receiver.pubkey(), - &native_token_mint_key, - ); + // println!("full denom {:?}", x.denom.to_string()); + // println!( + // "hashed full denom {:?}", + // lib::hash::CryptoHash::digest(x.denom.to_string().as_bytes()) + // ); + + // Initialize the progroam to define the auctioneer + println!("\nInitializing the program"); + let sig = program + .request() + .accounts(crate::accounts::Initialize { + authority: auctioneer.pubkey(), + auctioneer: auctioneer_state, + system_program: anchor_lang::solana_program::system_program::ID, + }) + .args(crate::instruction::Initialize {}) + .payer(auctioneer.clone()) + .signer(&*auctioneer) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }) + .unwrap(); + println!(" Signature: {}", sig); + + let token_in_escrow_addr = + get_associated_token_address(&auctioneer_state, &token_in); + + // Escrow user funds + println!("Escrow user funds"); + let sig = program + .request() + .accounts(crate::accounts::EscrowFunds { + user: user.pubkey(), + user_token_account: user_token_in_addr, + auctioneer_state, + token_mint: token_in, + escrow_token_account: token_in_escrow_addr, + token_program: anchor_spl::token::ID, + associated_token_program: associated_token::ID, + system_program: system_program::ID, + }) + .args(crate::instruction::EscrowFunds { amount: TRANSFER_AMOUNT }) + .payer(user.clone()) + .signer(&*user) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }) + .unwrap(); + println!(" Signature: {}", sig); + + // Store the intent + let intent_id = "123234".to_string(); + + // arbitrary value + let amount_out = 10000; + + let intent_state = Pubkey::find_program_address( + &[crate::INTENT_SEED, intent_id.as_bytes()], + &crate::ID, + ) + .0; + + let sig = program + .request() + .accounts(crate::accounts::StoreIntent { + authority: auctioneer.pubkey(), + intent: intent_state, + auctioneer: auctioneer_state, + system_program: anchor_lang::solana_program::system_program::ID, + }) + .args(crate::instruction::StoreIntent { + intent_id: intent_id.clone(), + user_in: user.pubkey(), + token_in, + amount_in: TRANSFER_AMOUNT, + token_out: token_out.to_string(), + amount_out: amount_out.to_string(), + timeout_in_sec: 10000, + winner_solver: solver.pubkey(), + }) + .payer(auctioneer.clone()) + .signer(&*auctioneer) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }) + .unwrap(); + println!(" Signature: {}", sig); + + // Send funds to user ( single domain ) + + let solver_token_in_addr = + get_associated_token_address(&solver.pubkey(), &token_in); + let user_token_out_addr = + get_associated_token_address(&user.pubkey(), &token_out); + + let sig = program + .request() + .accounts(crate::accounts::SplTokenTransfer { + solver: solver.pubkey(), + intent: intent_state, + auctioneer_state, + auctioneer: auctioneer.pubkey(), + token_in, + token_out, + auctioneer_token_in_account: token_in_escrow_addr, + solver_token_in_account: solver_token_in_addr, + solver_token_out_account: solver_token_out_addr, + user_token_out_account: user_token_out_addr, + token_program: anchor_spl::token::ID, + associated_token_program: anchor_spl::associated_token::ID, + system_program: anchor_lang::solana_program::system_program::ID, + ibc_program: None, + receiver: None, + storage: None, + trie: None, + chain: None, + mint_authority: None, + token_mint: None, + escrow_account: None, + receiver_token_account: None, + fee_collector: None, + }) + .args(crate::instruction::SendFundsToUser { + intent_id, + hashed_full_denom: None, + solver_out: None, + single_domain: true, + }) + .payer(solver.clone()) + .signer(&*solver) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }) + .unwrap(); + println!(" Signature: {}", sig); + + // If above fails -> timeout + + // // Derive the necessary accounts + // let (storage, _bump_storage) = Pubkey::find_program_address( + // &[solana_ibc::SOLANA_IBC_STORAGE_SEED], + // &solana_ibc::ID, + // ); + // let (trie, _bump_trie) = + // Pubkey::find_program_address(&[solana_ibc::TRIE_SEED], &solana_ibc::ID); + // let (chain, _bump_chain) = Pubkey::find_program_address( + // &[solana_ibc::CHAIN_SEED], + // &solana_ibc::ID, + // ); + // let (mint_authority, _bump_mint_authority) = Pubkey::find_program_address( + // &[solana_ibc::MINT_ESCROW_SEED], + // &solana_ibc::ID, + // ); + // let (escrow_account, _bump_escrow_account) = Pubkey::find_program_address( + // &[solana_ibc::ESCROW, &hashed_full_denom.as_slice()], + // &solana_ibc::ID, + // ); + + // let receiver_token_account = get_associated_token_address( + // &authority.pubkey(), + // &native_token_mint_key, + // ); + // let (fee_collector, _bump_fee_collector) = + // Pubkey::find_program_address(&[solana_ibc::FEE_SEED], &solana_ibc::ID); + + // let system_program = anchor_lang::system_program::ID; + + // // Amount to transfer + // let amount = 1000000; // Example amount + + // let destination_token_account = get_associated_token_address( + // &receiver.pubkey(), + // &native_token_mint_key, + // ); - // Build and send the transaction to call send_funds_to_user + // // Build and send the transaction to call send_funds_to_user // println!("\nSending funds to user"); // let sig = program // .request() @@ -196,6 +390,11 @@ fn escrow_bridge_program() -> Result<()> { // token_program: anchor_spl::token::ID, // associated_token_program: anchor_spl::associated_token::ID, // system_program, + // intent: todo!(), + // auctioneer: todo!(), + // auctioneer_token_in_account: todo!(), + // solver_token_out_account: todo!(), + // auctioneer_token_out_account: todo!(), // }) // .args(crate::instruction::SendFundsToUser { amount, hashed_full_denom }) // .payer(authority.clone()) diff --git a/solana/restaking/programs/restaking/src/lib.rs b/solana/restaking/programs/restaking/src/lib.rs index 4bcf295e..8be7de0d 100644 --- a/solana/restaking/programs/restaking/src/lib.rs +++ b/solana/restaking/programs/restaking/src/lib.rs @@ -16,7 +16,7 @@ use constants::{ VAULT_PARAMS_SEED, VAULT_SEED, }; -declare_id!("9JkWjSfc5Yb5EdTwhxHDx6rh8usXYVFm9KFwqzskVE8t"); +declare_id!("8n3FHwYxFgQCQc2FNFkwDUf9mcqupxXcCvgfHbApMLv3"); #[program] pub mod restaking { diff --git a/solana/solana-ibc/programs/solana-ibc/src/lib.rs b/solana/solana-ibc/programs/solana-ibc/src/lib.rs index ab0070b2..aa58c9c9 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/lib.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/lib.rs @@ -33,7 +33,7 @@ pub const WSOL_ADDRESS: &str = "So11111111111111111111111111111111111111112"; pub const MINIMUM_FEE_ACCOUNT_BALANCE: u64 = solana_program::native_token::LAMPORTS_PER_SOL; -declare_id!("3JvDhxt87SqKwNSuBPWWSRsfSxzkjzofDh1B6DioqfQ3"); +declare_id!("2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"); #[cfg(not(feature = "mocks"))] mod relayer { From 2f45602d845b22eeaa392470c8a5014890bbb159 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Wed, 14 Aug 2024 05:12:32 +0530 Subject: [PATCH 12/47] assert tests conditiosn --- .../programs/bridge-escrow/src/lib.rs | 6 ++- .../programs/bridge-escrow/src/tests.rs | 43 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index d81e14fc..04160f90 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -153,6 +153,10 @@ pub mod bridge_escrow { let token_program = &ctx.accounts.token_program; let solver = &ctx.accounts.solver; + let amount_out = intent.amount_out.parse::().map_err(|_| { + ErrorCode::InvalidAmount + })?; + // Transfer tokens from Solver to User let cpi_accounts = SplTransfer { from: ctx @@ -166,7 +170,7 @@ pub mod bridge_escrow { let cpi_program = token_program.to_account_info(); token::transfer( CpiContext::new(cpi_program, cpi_accounts), - intent.amount_in, + amount_out, )?; if single_domain { diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index 5c942c3e..7bea10b8 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -217,6 +217,10 @@ fn escrow_bridge_program() -> Result<()> { // Escrow user funds println!("Escrow user funds"); + + let user_token_in_balance_before = + sol_rpc_client.get_token_account_balance(&user_token_in_addr).unwrap(); + let sig = program .request() .accounts(crate::accounts::EscrowFunds { @@ -239,6 +243,17 @@ fn escrow_bridge_program() -> Result<()> { .unwrap(); println!(" Signature: {}", sig); + let user_token_in_balance_after = + sol_rpc_client.get_token_account_balance(&user_token_in_addr).unwrap(); + + // assert_eq!( + // ((user_token_in_balance_after.ui_amount.unwrap() + // - user_token_in_balance_before.ui_amount.unwrap()) + // * 1_000_000f64) + // .round() as u64, + // TRANSFER_AMOUNT + // ); + // Store the intent let intent_id = "123234".to_string(); @@ -285,6 +300,12 @@ fn escrow_bridge_program() -> Result<()> { let user_token_out_addr = get_associated_token_address(&user.pubkey(), &token_out); + let solver_token_in_balance_before = sol_rpc_client + .get_token_account_balance(&solver_token_in_addr) + .unwrap(); + let user_token_out_balance_before = + sol_rpc_client.get_token_account_balance(&user_token_out_addr).unwrap(); + let sig = program .request() .accounts(crate::accounts::SplTokenTransfer { @@ -327,6 +348,28 @@ fn escrow_bridge_program() -> Result<()> { .unwrap(); println!(" Signature: {}", sig); + let solver_token_in_balance_after = sol_rpc_client + .get_token_account_balance(&solver_token_in_addr) + .unwrap(); + let user_token_out_balance_after = + sol_rpc_client.get_token_account_balance(&user_token_out_addr).unwrap(); + + assert_eq!( + ((solver_token_in_balance_after.ui_amount.unwrap() + - solver_token_in_balance_before.ui_amount.unwrap()) + * 1_000_000f64) + .round() as u64, + TRANSFER_AMOUNT + ); + + assert_eq!( + ((user_token_out_balance_after.ui_amount.unwrap() + - user_token_out_balance_before.ui_amount.unwrap()) + * 1_000_000f64) + .round() as u64, + amount_out + ); + // If above fails -> timeout // // Derive the necessary accounts From 9ee702593b54f1bdbb653305b2391e379b587c0b Mon Sep 17 00:00:00 2001 From: banegil Date: Mon, 19 Aug 2024 13:59:44 +0200 Subject: [PATCH 13/47] bridge escrow - auctioneer_transfer --- Anchor.toml | 8 ++-- .../programs/bridge-escrow/src/lib.rs | 42 ++++++++++++++++++- .../restaking/programs/restaking/src/lib.rs | 2 +- .../solana-ibc/programs/solana-ibc/src/lib.rs | 2 +- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/Anchor.toml b/Anchor.toml index ae54b40d..0b183634 100644 --- a/Anchor.toml +++ b/Anchor.toml @@ -6,13 +6,13 @@ skip-lint = false [programs.devnet] bridge-escrow = "A5ygmioT2hWFnxpPapY3XyDjwwfMDhnSP1Yxoynd5hs4" -restaking = "8n3FHwYxFgQCQc2FNFkwDUf9mcqupxXcCvgfHbApMLv3" -solana_ibc = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT" +restaking = "JEG7nDQFRPFjjFgWVXaA25EkcXGVjma2Cy56C976sXhk" +solana_ibc = "EUiJni1BZFL3BhaWcS7NTJmqWyh8NwRLjBzrcGBvxKU4" [programs.localnet] bridge-escrow = "A5ygmioT2hWFnxpPapY3XyDjwwfMDhnSP1Yxoynd5hs4" -restaking = "8n3FHwYxFgQCQc2FNFkwDUf9mcqupxXcCvgfHbApMLv3" -solana_ibc = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT" +restaking = "JEG7nDQFRPFjjFgWVXaA25EkcXGVjma2Cy56C976sXhk" +solana_ibc = "EUiJni1BZFL3BhaWcS7NTJmqWyh8NwRLjBzrcGBvxKU4" [registry] url = "https://api.apr.dev" diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 04160f90..bce904e0 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -29,7 +29,7 @@ const INTENT_SEED: &[u8] = b"intent"; #[cfg(test)] mod tests; -declare_id!("43VAmkAMHhRMX124zHZiQDk9SwbXqhZaWDvGrfeo4eHv"); +declare_id!("EcKk7ZzNPHBougPDZ2Rwu93xd48ba1X6cwW1j8DUChHP"); #[program] pub mod bridge_escrow { @@ -61,6 +61,33 @@ pub mod bridge_escrow { Ok(()) } + /// Transfers funds from the auctioneer's escrow account to a specified recipient. + /// + /// The funds are stored in a token account owned by the auctioneer state PDA. + pub fn auctioneer_transfer(ctx: Context, amount: u64) -> Result<()> { + // Transfer SPL tokens from the auctioneer's escrow account to the recipient's account + let cpi_accounts = SplTransfer { + from: ctx.accounts.escrow_token_account.to_account_info(), + to: ctx.accounts.recipient_token_account.to_account_info(), + authority: ctx.accounts.auctioneer_state.to_account_info(), + }; + + let cpi_program = ctx.accounts.token_program.to_account_info(); + + // Retrieve the bump seed using the `seeds` provided in the context + let auctioneer_seeds = &[ + AUCTIONEER_SEED.as_ref(), + &[ctx.bumps.auctioneer_state] + ]; + let signer_seeds = &[&auctioneer_seeds[..]]; + + let cpi_ctx = CpiContext::new_with_signer(cpi_program, cpi_accounts, signer_seeds); + + token::transfer(cpi_ctx, amount)?; + + Ok(()) + } + /// Called by the auctioneer whose address is stored in `auctioneer` state account. pub fn store_intent( ctx: Context, @@ -139,7 +166,6 @@ pub mod bridge_escrow { // this function is called by Solver pub fn send_funds_to_user( ctx: Context, - intent_id: String, hashed_full_denom: Option, solver_out: Option, single_domain: bool, @@ -567,3 +593,15 @@ pub enum ErrorCode { #[msg("Invalid hashed full denom")] InvalidHashedFullDenom, } + +#[derive(Accounts)] +pub struct AuctioneerTransfer<'info> { + #[account(seeds = [AUCTIONEER_SEED], bump)] + pub auctioneer_state: Account<'info, Auctioneer>, // The PDA representing the auctioneer's state + #[account(mut, token::authority = auctioneer_state)] + pub escrow_token_account: Account<'info, TokenAccount>, // PDA's token account holding escrowed funds + #[account(mut)] + pub recipient_token_account: Account<'info, TokenAccount>, // Recipient's token account + pub token_program: Program<'info, Token>, // Token program reference +} + diff --git a/solana/restaking/programs/restaking/src/lib.rs b/solana/restaking/programs/restaking/src/lib.rs index 8be7de0d..717fc5f2 100644 --- a/solana/restaking/programs/restaking/src/lib.rs +++ b/solana/restaking/programs/restaking/src/lib.rs @@ -16,7 +16,7 @@ use constants::{ VAULT_PARAMS_SEED, VAULT_SEED, }; -declare_id!("8n3FHwYxFgQCQc2FNFkwDUf9mcqupxXcCvgfHbApMLv3"); +declare_id!("JEG7nDQFRPFjjFgWVXaA25EkcXGVjma2Cy56C976sXhk"); #[program] pub mod restaking { diff --git a/solana/solana-ibc/programs/solana-ibc/src/lib.rs b/solana/solana-ibc/programs/solana-ibc/src/lib.rs index aa58c9c9..f284173e 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/lib.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/lib.rs @@ -33,7 +33,7 @@ pub const WSOL_ADDRESS: &str = "So11111111111111111111111111111111111111112"; pub const MINIMUM_FEE_ACCOUNT_BALANCE: u64 = solana_program::native_token::LAMPORTS_PER_SOL; -declare_id!("2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"); +declare_id!("EUiJni1BZFL3BhaWcS7NTJmqWyh8NwRLjBzrcGBvxKU4"); #[cfg(not(feature = "mocks"))] mod relayer { From 3255b59518d0d0baaea9e57384e1bcfd8de852fc Mon Sep 17 00:00:00 2001 From: banegil Date: Mon, 19 Aug 2024 14:18:58 +0200 Subject: [PATCH 14/47] remove auctioner_trasnfer() on escrow Program --- common/cf-guest/src/client.rs | 8 ++- common/cf-guest/src/client/impls.rs | 13 ++-- common/cf-guest/src/client/tests.rs | 2 - common/cf-guest/src/header.rs | 5 +- common/cf-guest/src/message.rs | 37 +++++++---- common/cf-guest/src/misbehaviour.rs | 4 +- common/cf-guest/src/proof.rs | 21 ++++--- common/guestchain/src/block.rs | 12 ++-- common/guestchain/src/candidates.rs | 12 +++- common/guestchain/src/candidates/tests.rs | 24 +++---- common/guestchain/src/epoch.rs | 4 +- common/guestchain/src/height.rs | 24 +++++-- common/guestchain/src/manager.rs | 22 ++++--- common/guestchain/src/validators.rs | 24 +++++-- common/lib/src/hash.rs | 45 +++++++++---- common/lib/src/u3.rs | 24 +++++-- common/memory/src/lib.rs | 12 +++- common/proto-utils/src/lib.rs | 8 +-- common/proto-utils/src/tests.rs | 8 ++- common/sealable-trie/src/bits.rs | 55 ++++++++++------ common/sealable-trie/src/bits/concat.rs | 13 ++-- common/sealable-trie/src/bits/ext_key.rs | 14 +++-- common/sealable-trie/src/nodes.rs | 9 ++- common/sealable-trie/src/proof.rs | 28 ++++++--- .../sealable-trie/src/proof/serialisation.rs | 15 ++--- common/sealable-trie/src/trie.rs | 17 +++-- common/sealable-trie/src/trie/del.rs | 4 +- common/sealable-trie/src/trie/tests.rs | 63 +++++++++++++------ common/trie-ids/src/ids.rs | 52 +++++++++++---- common/trie-ids/src/path_info.rs | 5 +- common/trie-ids/src/trie_key.rs | 23 ++++--- common/wasm/src/consensus_state.rs | 4 +- solana/allocator/src/lib.rs | 4 +- solana/allocator/src/ptr.rs | 1 - .../programs/bridge-escrow/src/lib.rs | 46 ++------------ .../restaking/programs/restaking/src/lib.rs | 8 +-- .../restaking/programs/restaking/src/token.rs | 38 ++++++----- solana/signature-verifier/src/api.rs | 7 +-- solana/signature-verifier/src/ed25519.rs | 16 +++-- .../signature-verifier/src/ed25519_program.rs | 31 ++++++--- solana/signature-verifier/src/program.rs | 3 - solana/signature-verifier/src/verifier.rs | 8 ++- .../programs/solana-ibc/src/allocator.rs | 4 +- .../programs/solana-ibc/src/chain.rs | 12 +++- .../solana-ibc/src/client_state/impls.rs | 24 +++++-- .../solana-ibc/src/consensus_state.rs | 1 - .../programs/solana-ibc/src/error.rs | 20 ++++-- .../programs/solana-ibc/src/events.rs | 2 - .../solana-ibc/src/execution_context.rs | 13 ++-- .../solana-ibc/src/ix_data_account.rs | 17 +++-- .../solana-ibc/programs/solana-ibc/src/lib.rs | 19 +++--- .../programs/solana-ibc/src/mocks.rs | 2 - .../programs/solana-ibc/src/storage.rs | 26 +++++--- .../programs/solana-ibc/src/storage/map.rs | 12 +++- .../programs/solana-ibc/src/tests.rs | 24 +++---- .../programs/solana-ibc/src/transfer/impls.rs | 20 +++--- .../solana-ibc/src/validation_context.rs | 10 +-- solana/trie-example/src/lib.rs | 1 - solana/trie/src/account.rs | 8 ++- solana/trie/src/alloc.rs | 13 ++-- solana/trie/src/data_ref.rs | 36 ++++++++--- solana/trie/src/header.rs | 1 - solana/trie/src/lib.rs | 14 +++-- solana/write-account/src/program.rs | 4 -- validator/src/main.rs | 4 +- 65 files changed, 670 insertions(+), 390 deletions(-) diff --git a/common/cf-guest/src/client.rs b/common/cf-guest/src/client.rs index 3502bc60..1fffb0e9 100644 --- a/common/cf-guest/src/client.rs +++ b/common/cf-guest/src/client.rs @@ -96,11 +96,15 @@ impl ClientState { this } - pub fn frozen(&self) -> Self { Self { is_frozen: true, ..self.clone() } } + pub fn frozen(&self) -> Self { + Self { is_frozen: true, ..self.clone() } + } } impl From> for proto::ClientState { - fn from(state: ClientState) -> Self { Self::from(&state) } + fn from(state: ClientState) -> Self { + Self::from(&state) + } } impl From<&ClientState> for proto::ClientState { diff --git a/common/cf-guest/src/client/impls.rs b/common/cf-guest/src/client/impls.rs index 48e84a82..e83baca4 100644 --- a/common/cf-guest/src/client/impls.rs +++ b/common/cf-guest/src/client/impls.rs @@ -43,7 +43,9 @@ pub enum Neighbourhood { } impl Default for Neighbourhood { - fn default() -> Self { Self::Neighbours(None, None) } + fn default() -> Self { + Self::Neighbours(None, None) + } } impl Neighbourhood { @@ -237,7 +239,6 @@ impl ibc::ClientStateCommon for ClientState { } } - impl From for ibc::ClientError { fn from(err: proof::VerifyError) -> Self { use ibc::CommitmentError::EncodingFailure; @@ -396,7 +397,6 @@ where } } - impl ClientState { pub fn do_update_state( &self, @@ -480,8 +480,8 @@ impl ClientState { if header.genesis_hash != self.genesis_hash { return Err("Unexpected genesis hash"); } - if header.epoch_commitment != self.epoch_commitment && - header.epoch_commitment != self.prev_epoch_commitment + if header.epoch_commitment != self.epoch_commitment + && header.epoch_commitment != self.prev_epoch_commitment { return Err("Unexpected epoch"); } @@ -641,12 +641,10 @@ impl ClientState { } } - fn error(msg: impl ToString) -> ibc::ClientError { ibc::ClientError::Other { description: msg.to_string() } } - /// Checks client id’s client type is what’s expected and then parses the id as /// `ClientIdx`. /// @@ -666,7 +664,6 @@ fn parse_client_id(client_id: &ibc::ClientId) -> Result { Err(ibc::ClientError::ClientSpecific { description }) } - #[test] fn test_verify_client_type() { use core::str::FromStr; diff --git a/common/cf-guest/src/client/tests.rs b/common/cf-guest/src/client/tests.rs index 0ee5045b..defd655e 100644 --- a/common/cf-guest/src/client/tests.rs +++ b/common/cf-guest/src/client/tests.rs @@ -131,7 +131,6 @@ fn test_header_misbehaviour() { add_block(&mut ctx, Some(&bad_block_2), 25 * HOUR, 2, Ok(true), None); } - /// Tests Misbehaviour client messages. /// /// Only verification and checking for misbehaviour are tested. No state @@ -302,7 +301,6 @@ impl TestContext { } } - impl guestchain::Verifier for TestContext { fn verify( &self, diff --git a/common/cf-guest/src/header.rs b/common/cf-guest/src/header.rs index e7df4978..25855d99 100644 --- a/common/cf-guest/src/header.rs +++ b/common/cf-guest/src/header.rs @@ -71,7 +71,9 @@ impl Header { } impl From> for proto::Header { - fn from(header: Header) -> Self { Self::from(&header) } + fn from(header: Header) -> Self { + Self::from(&header) + } } impl From<&Header> for proto::Header { @@ -169,7 +171,6 @@ impl Header { } } - proto_utils::define_wrapper! { proto: proto::Header, wrapper: Header where diff --git a/common/cf-guest/src/message.rs b/common/cf-guest/src/message.rs index 43099250..0503b786 100644 --- a/common/cf-guest/src/message.rs +++ b/common/cf-guest/src/message.rs @@ -15,11 +15,12 @@ pub enum ClientMessage { Misbehaviour(Misbehaviour), } - // Conversions directly to and from the Message enum. impl From> for Message { - fn from(msg: ClientMessage) -> Self { Self::from(&msg) } + fn from(msg: ClientMessage) -> Self { + Self::from(&msg) + } } impl From<&ClientMessage> for Message { @@ -48,34 +49,44 @@ impl TryFrom<&Message> for ClientMessage { } } - // Conversions directly into the Message enum from variant types. impl From> for Message { - fn from(msg: Header) -> Self { Self::Header(msg.into()) } + fn from(msg: Header) -> Self { + Self::Header(msg.into()) + } } impl From<&Header> for Message { - fn from(msg: &Header) -> Self { Self::Header(msg.into()) } + fn from(msg: &Header) -> Self { + Self::Header(msg.into()) + } } impl From> for Message { - fn from(msg: Misbehaviour) -> Self { Self::Misbehaviour(msg.into()) } + fn from(msg: Misbehaviour) -> Self { + Self::Misbehaviour(msg.into()) + } } impl From<&Misbehaviour> for Message { - fn from(msg: &Misbehaviour) -> Self { Self::Misbehaviour(msg.into()) } + fn from(msg: &Misbehaviour) -> Self { + Self::Misbehaviour(msg.into()) + } } - // Conversion into ClientMessage proto from variant types. impl From> for proto::ClientMessage { - fn from(msg: Header) -> Self { Self { message: Some(msg.into()) } } + fn from(msg: Header) -> Self { + Self { message: Some(msg.into()) } + } } impl From<&Header> for proto::ClientMessage { - fn from(msg: &Header) -> Self { Self { message: Some(msg.into()) } } + fn from(msg: &Header) -> Self { + Self { message: Some(msg.into()) } + } } impl From> for proto::ClientMessage { @@ -90,11 +101,12 @@ impl From<&Misbehaviour> for proto::ClientMessage { } } - // And finally, conversions between proto and Rust type impl From> for proto::ClientMessage { - fn from(msg: ClientMessage) -> Self { Self::from(&msg) } + fn from(msg: ClientMessage) -> Self { + Self::from(&msg) + } } impl From<&ClientMessage> for proto::ClientMessage { @@ -125,7 +137,6 @@ impl TryFrom<&proto::ClientMessage> } } - proto_utils::define_wrapper! { proto: proto::ClientMessage, wrapper: ClientMessage where diff --git a/common/cf-guest/src/misbehaviour.rs b/common/cf-guest/src/misbehaviour.rs index 73e7fe32..73da6a84 100644 --- a/common/cf-guest/src/misbehaviour.rs +++ b/common/cf-guest/src/misbehaviour.rs @@ -9,7 +9,9 @@ pub struct Misbehaviour { } impl From> for proto::Misbehaviour { - fn from(msg: Misbehaviour) -> Self { Self::from(&msg) } + fn from(msg: Misbehaviour) -> Self { + Self::from(&msg) + } } impl From<&Misbehaviour> for proto::Misbehaviour { diff --git a/common/cf-guest/src/proof.rs b/common/cf-guest/src/proof.rs index d1d710e9..8257dadd 100644 --- a/common/cf-guest/src/proof.rs +++ b/common/cf-guest/src/proof.rs @@ -23,10 +23,14 @@ pub struct IbcProof { impl IbcProof { /// Returns commitment prefix to use during verification. - pub fn prefix(&self) -> ibc::CommitmentPrefix { Default::default() } + pub fn prefix(&self) -> ibc::CommitmentPrefix { + Default::default() + } /// Returns commitment root. - pub fn root(&self) -> ibc::CommitmentRoot { self.root.to_vec().into() } + pub fn root(&self) -> ibc::CommitmentRoot { + self.root.to_vec().into() + } /// Consumes object and returns commitment proof. pub fn proof(self) -> ibc::CommitmentProofBytes { @@ -34,7 +38,6 @@ impl IbcProof { } } - #[derive(Clone, Debug, PartialEq, Eq, derive_more::From)] pub enum GenerateError { /// State root in block header and root of trie don’t match. @@ -104,7 +107,6 @@ pub fn generate( Ok(IbcProof { proof, root, value }) } - #[derive( Clone, Debug, PartialEq, Eq, derive_more::From, derive_more::Display, )] @@ -186,9 +188,9 @@ pub fn verify( <&CryptoHash>::try_from(root).map_err(|_| VerifyError::BadRoot)?; let is_packet_commitment = matches!( path, - ibc::path::Path::Commitment(_) | - ibc::path::Path::Receipt(_) | - ibc::path::Path::Ack(_) + ibc::path::Path::Commitment(_) + | ibc::path::Path::Receipt(_) + | ibc::path::Path::Ack(_) ); let path = trie_ids::PathInfo::try_from(path)?; @@ -253,7 +255,6 @@ pub fn verify( } } - #[test] fn test_proofs() { use core::str::FromStr; @@ -273,7 +274,9 @@ fn test_proofs() { self.header.state_root = self.trie.hash().clone(); } - fn root(&self) -> &CryptoHash { self.trie.hash() } + fn root(&self) -> &CryptoHash { + self.trie.hash() + } } /// Takes a proof and substitutes the block header encoded in it. diff --git a/common/guestchain/src/block.rs b/common/guestchain/src/block.rs index 478ee294..58935c4c 100644 --- a/common/guestchain/src/block.rs +++ b/common/guestchain/src/block.rs @@ -187,8 +187,8 @@ impl BlockHeader { /// Returns whether the block is a valid genesis block. pub fn is_genesis(&self) -> bool { - self.prev_block_hash == CryptoHash::DEFAULT && - self.epoch_id == CryptoHash::DEFAULT + self.prev_block_hash == CryptoHash::DEFAULT + && self.epoch_id == CryptoHash::DEFAULT } /// Calculates hash of the block. @@ -268,7 +268,9 @@ impl Block { } impl Default for Fingerprint { - fn default() -> Self { Self([0; 72]) } + fn default() -> Self { + Self([0; 72]) + } } impl Fingerprint { @@ -304,7 +306,9 @@ impl Fingerprint { /// Returns the fingerprint as bytes slice. #[inline] - pub fn as_slice(&self) -> &[u8] { &self.0[..] } + pub fn as_slice(&self) -> &[u8] { + &self.0[..] + } /// Signs the fingerprint #[inline] diff --git a/common/guestchain/src/candidates.rs b/common/guestchain/src/candidates.rs index 8319308d..4e72177c 100644 --- a/common/guestchain/src/candidates.rs +++ b/common/guestchain/src/candidates.rs @@ -93,7 +93,9 @@ impl Candidates { } /// Returns stake held by first `max_validators` candidates. - pub fn current_head_stake(&self) -> u128 { self.head_stake } + pub fn current_head_stake(&self) -> u128 { + self.head_stake + } /// Sums stake of the first `count` candidates. fn sum_head_stake(count: NonZeroU16, candidates: &[Candidate]) -> u128 { @@ -135,7 +137,9 @@ impl Candidates { /// Changed flag is set automatically whenever head of the candidates list /// is modified (note that changes outside of the head of candidates list do /// not affect the flag). - pub fn clear_changed_flag(&mut self) { self.changed = false; } + pub fn clear_changed_flag(&mut self) { + self.changed = false; + } /// Adds a new candidates or updates existing candidate’s stake. /// @@ -332,7 +336,9 @@ impl Candidates { impl Candidates { /// Convenience method which returns `self.max_validators` as `usize`. - fn max_validators(&self) -> usize { usize::from(self.max_validators.get()) } + fn max_validators(&self) -> usize { + usize::from(self.max_validators.get()) + } } /// Rotates subslice such that element at `old_pos` moves to `new_pos`. diff --git a/common/guestchain/src/candidates/tests.rs b/common/guestchain/src/candidates/tests.rs index ce49383c..a7adf3db 100644 --- a/common/guestchain/src/candidates/tests.rs +++ b/common/guestchain/src/candidates/tests.rs @@ -127,7 +127,9 @@ fn test_candidates_0() { use candidate as c; use UpdateCandidateError::*; - fn pk(pubkey: char) -> MockPubKey { MockPubKey(pubkey as u32) } + fn pk(pubkey: char) -> MockPubKey { + MockPubKey(pubkey as u32) + } // Create candidates set let mut candidates = Candidates::from_candidates( @@ -303,8 +305,8 @@ impl TestCtx { /// configuration file. fn check(&self) { assert!( - self.candidates.candidates.len() >= - usize::from(self.config.min_validators.get()), + self.candidates.candidates.len() + >= usize::from(self.config.min_validators.get()), "Violated min validators constraint: {} < {}", self.candidates.candidates.len(), self.config.min_validators.get(), @@ -345,14 +347,14 @@ impl TestCtx { .get(usize::from(self.config.max_validators.get())) .map_or(0, |c: &Candidate<_>| c.stake.get()); assert!( - head_stake - old_stake + new_stake < - self.config.min_total_stake.get() + head_stake - old_stake + new_stake + < self.config.min_total_stake.get() ); } NotEnoughValidators => { assert!( - self.candidates.candidates.len() <= - usize::from(self.config.min_validators.get()) + self.candidates.candidates.len() + <= usize::from(self.config.min_validators.get()) ); } } @@ -425,8 +427,8 @@ impl TestCtx { .candidates .get(usize::from(self.config.max_validators.get())); let kicked_out = last.clone().map_or(false, |candidiate| { - candidiate < - &Candidate { + candidiate + < &Candidate { pubkey, stake: NonZeroU128::new(new_stake).unwrap(), } @@ -436,8 +438,8 @@ impl TestCtx { if kicked_out { last.unwrap().stake.get() } else { new_stake }; assert!( - self.candidates.head_stake - old_stake + new_stake < - self.config.min_total_stake.get() + self.candidates.head_stake - old_stake + new_stake + < self.config.min_total_stake.get() ); } diff --git a/common/guestchain/src/epoch.rs b/common/guestchain/src/epoch.rs index 75620e75..3a33be04 100644 --- a/common/guestchain/src/epoch.rs +++ b/common/guestchain/src/epoch.rs @@ -96,7 +96,9 @@ impl Epoch { } /// Returns stake needed to reach quorum. - pub fn quorum_stake(&self) -> NonZeroU128 { self.quorum_stake } + pub fn quorum_stake(&self) -> NonZeroU128 { + self.quorum_stake + } /// Finds a validator by their public key. pub fn validator(&self, pk: &PK) -> Option<&crate::Validator> diff --git a/common/guestchain/src/height.rs b/common/guestchain/src/height.rs index a7d6f253..2513f903 100644 --- a/common/guestchain/src/height.rs +++ b/common/guestchain/src/height.rs @@ -31,7 +31,9 @@ pub type BlockDelta = Delta; impl Height { /// Returns the next height, i.e. `self + 1`. - pub fn next(self) -> Self { Self(self.0.checked_add(1).unwrap(), self.1) } + pub fn next(self) -> Self { + Self(self.0.checked_add(1).unwrap(), self.1) + } /// Checks whether delta between two heights is at least `min`. /// @@ -51,17 +53,23 @@ impl Height { macro_rules! impls { ($ty:ident) => { impl Clone for $ty { - fn clone(&self) -> Self { *self } + fn clone(&self) -> Self { + *self + } } impl Copy for $ty {} impl From for $ty { - fn from(value: u64) -> Self { Self(value, Default::default()) } + fn from(value: u64) -> Self { + Self(value, Default::default()) + } } impl From<$ty> for u64 { - fn from(value: $ty) -> u64 { value.0 } + fn from(value: $ty) -> u64 { + value.0 + } } impl fmt::Debug for $ty { @@ -77,7 +85,9 @@ macro_rules! impls { } impl PartialEq for $ty { - fn eq(&self, rhs: &Self) -> bool { self.0 == rhs.0 } + fn eq(&self, rhs: &Self) -> bool { + self.0 == rhs.0 + } } impl Eq for $ty {} @@ -89,7 +99,9 @@ macro_rules! impls { } impl Ord for $ty { - fn cmp(&self, rhs: &Self) -> cmp::Ordering { self.0.cmp(&rhs.0) } + fn cmp(&self, rhs: &Self) -> cmp::Ordering { + self.0.cmp(&rhs.0) + } } impl borsh::BorshSerialize for $ty { diff --git a/common/guestchain/src/manager.rs b/common/guestchain/src/manager.rs index 282b78a8..ac2ec4d4 100644 --- a/common/guestchain/src/manager.rs +++ b/common/guestchain/src/manager.rs @@ -120,8 +120,12 @@ pub enum AddSignatureEffect { } impl AddSignatureEffect { - pub fn got_new_signature(self) -> bool { self != Self::Duplicate } - pub fn got_quorum(self) -> bool { self == Self::GotQuorum } + pub fn got_new_signature(self) -> bool { + self != Self::Duplicate + } + pub fn got_quorum(self) -> bool { + self == Self::GotQuorum + } } impl ChainManager { @@ -251,9 +255,9 @@ impl ChainManager { let next_epoch = self.maybe_generate_next_epoch(host_height); let age = host_timestamp.get().saturating_sub(self.header.timestamp_ns.get()); - if next_epoch.is_none() && - state_root == &self.header.state_root && - age < self.config.max_block_age_ns + if next_epoch.is_none() + && state_root == &self.header.state_root + && age < self.config.max_block_age_ns { return Err(GenerateError::UnchangedState); }; @@ -356,9 +360,13 @@ impl ChainManager { self.candidates.candidates.as_slice() } - pub fn epoch_height(&self) -> crate::HostHeight { self.epoch_height } + pub fn epoch_height(&self) -> crate::HostHeight { + self.epoch_height + } - pub fn genesis(&self) -> &CryptoHash { &self.genesis } + pub fn genesis(&self) -> &CryptoHash { + &self.genesis + } } #[test] diff --git a/common/guestchain/src/validators.rs b/common/guestchain/src/validators.rs index 4b663e81..8f5d40e9 100644 --- a/common/guestchain/src/validators.rs +++ b/common/guestchain/src/validators.rs @@ -19,7 +19,9 @@ pub trait PubKey: type Signature: Signature; fn as_bytes(&self) -> alloc::borrow::Cow<'_, [u8]>; - fn to_vec(&self) -> Vec { self.as_bytes().into_owned() } + fn to_vec(&self) -> Vec { + self.as_bytes().into_owned() + } fn from_bytes(bytes: &[u8]) -> Result; } @@ -28,7 +30,9 @@ pub trait Signature: Clone + Eq + core::fmt::Debug + borsh::BorshSerialize + borsh::BorshDeserialize { fn as_bytes(&self) -> alloc::borrow::Cow<'_, [u8]>; - fn to_vec(&self) -> Vec { self.as_bytes().into_owned() } + fn to_vec(&self) -> Vec { + self.as_bytes().into_owned() + } fn from_bytes(bytes: &[u8]) -> Result; } @@ -70,13 +74,19 @@ impl Validator { Self { version: crate::common::VersionZero, pubkey, stake } } - pub fn pubkey(&self) -> &PK { &self.pubkey } + pub fn pubkey(&self) -> &PK { + &self.pubkey + } - pub fn stake(&self) -> NonZeroU128 { self.stake } + pub fn stake(&self) -> NonZeroU128 { + self.stake + } } impl From for BadFormat { - fn from(_: core::array::TryFromSliceError) -> BadFormat { BadFormat } + fn from(_: core::array::TryFromSliceError) -> BadFormat { + BadFormat + } } #[cfg(any(test, feature = "test_utils"))] @@ -99,7 +109,9 @@ pub(crate) mod test_utils { pub struct MockPubKey(pub u32); impl MockPubKey { - pub fn make_signer(&self) -> MockSigner { MockSigner(*self) } + pub fn make_signer(&self) -> MockSigner { + MockSigner(*self) + } } /// A mock implementation of a Signer. Offers no security; intended for diff --git a/common/lib/src/hash.rs b/common/lib/src/hash.rs index 1b84d873..15433dc7 100644 --- a/common/lib/src/hash.rs +++ b/common/lib/src/hash.rs @@ -39,7 +39,9 @@ impl CryptoHash { /// Returns a builder which can be used to construct cryptographic hash by /// digesting bytes. #[inline] - pub fn builder() -> Builder { Builder::default() } + pub fn builder() -> Builder { + Builder::default() + } /// Returns hash of given bytes. #[inline] @@ -59,7 +61,9 @@ impl CryptoHash { /// `solana` crate feature must be enabled for this Solana-specific /// optimisation to be implemented. #[inline] - pub fn digestv(slices: &[&[u8]]) -> Self { Self(imp::digestv(slices)) } + pub fn digestv(slices: &[&[u8]]) -> Self { + Self(imp::digestv(slices)) + } /// Decodes a base64 string representation of the hash. pub fn from_base64(base64: &str) -> Option { @@ -92,15 +96,21 @@ impl CryptoHash { /// Returns a shared reference to the underlying bytes array. #[inline] - pub fn as_array(&self) -> &[u8; Self::LENGTH] { &self.0 } + pub fn as_array(&self) -> &[u8; Self::LENGTH] { + &self.0 + } /// Returns a shared reference to the hash as slice of bytes. #[inline] - pub fn as_slice(&self) -> &[u8] { &self.0[..] } + pub fn as_slice(&self) -> &[u8] { + &self.0[..] + } /// Allocates vector with the contents of the hash. #[inline] - pub fn to_vec(&self) -> alloc::vec::Vec { self.as_slice().to_vec() } + pub fn to_vec(&self) -> alloc::vec::Vec { + self.as_slice().to_vec() + } } impl core::fmt::Display for CryptoHash { @@ -132,7 +142,9 @@ impl<'a> From<&'a [u8; CryptoHash::LENGTH]> for CryptoHash { impl From<&'_ CryptoHash> for [u8; CryptoHash::LENGTH] { #[inline] - fn from(hash: &'_ CryptoHash) -> Self { hash.0 } + fn from(hash: &'_ CryptoHash) -> Self { + hash.0 + } } impl<'a> From<&'a [u8; CryptoHash::LENGTH]> for &'a CryptoHash { @@ -193,10 +205,14 @@ mod imp { impl State { #[inline] - pub fn update(&mut self, bytes: &[u8]) { self.0.update(bytes) } + pub fn update(&mut self, bytes: &[u8]) { + self.0.update(bytes) + } #[inline] - pub fn done(self) -> [u8; 32] { self.0.finalize().into() } + pub fn done(self) -> [u8; 32] { + self.0.finalize().into() + } } } @@ -224,7 +240,6 @@ mod imp { } } - /// Builder for the cryptographic hash. /// /// The builder calculates the digest of bytes that it’s fed using the @@ -239,11 +254,15 @@ pub struct Builder(imp::State); impl Builder { /// Process data, updating the internal state of the digest. #[inline] - pub fn update(&mut self, bytes: &[u8]) { self.0.update(bytes) } + pub fn update(&mut self, bytes: &[u8]) { + self.0.update(bytes) + } /// Finalises the digest and returns the cryptographic hash. #[inline] - pub fn build(self) -> CryptoHash { CryptoHash(self.0.done()) } + pub fn build(self) -> CryptoHash { + CryptoHash(self.0.done()) + } } #[cfg(feature = "borsh")] @@ -257,7 +276,9 @@ impl io::Write for Builder { Ok(self.update(buf)) } - fn flush(&mut self) -> io::Result<()> { Ok(()) } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } } #[test] diff --git a/common/lib/src/u3.rs b/common/lib/src/u3.rs index 89dc8e90..307abff0 100644 --- a/common/lib/src/u3.rs +++ b/common/lib/src/u3.rs @@ -36,7 +36,9 @@ impl U3 { /// Divides argument by eight and returns quotient and reminder of the /// operation. - pub fn divmod(value: u16) -> (u16, U3) { (value / 8, Self::wrap(value)) } + pub fn divmod(value: u16) -> (u16, U3) { + (value / 8, Self::wrap(value)) + } /// Returns an iterator over all `U3` values in ascending order. pub fn all() -> impl core::iter::Iterator { @@ -48,14 +50,18 @@ impl U3 { } #[inline] - pub fn wrapping_inc(self) -> U3 { self.wrapping_add(1u8) } + pub fn wrapping_inc(self) -> U3 { + self.wrapping_add(1u8) + } pub fn wrapping_sub(self, rhs: impl Unsigned) -> U3 { U3::wrap(self.into_integer().wrapping_sub(rhs.as_u8())) } #[inline] - pub fn wrapping_dec(self) -> U3 { self.wrapping_add(7u8) } + pub fn wrapping_dec(self) -> U3 { + self.wrapping_add(7u8) + } #[inline] pub fn checked_inc(self) -> Option { @@ -70,16 +76,22 @@ impl U3 { impl Default for U3 { #[inline] - fn default() -> Self { Self::MIN } + fn default() -> Self { + Self::MIN + } } impl Unsigned for U3 { - fn as_u8(self) -> u8 { self.into_integer() } + fn as_u8(self) -> u8 { + self.into_integer() + } } impl ops::Neg for U3 { type Output = U3; - fn neg(self) -> U3 { U3::_0.wrapping_sub(self) } + fn neg(self) -> U3 { + U3::_0.wrapping_sub(self) + } } macro_rules! impls { diff --git a/common/memory/src/lib.rs b/common/memory/src/lib.rs index f8a7713a..813e1dae 100644 --- a/common/memory/src/lib.rs +++ b/common/memory/src/lib.rs @@ -193,7 +193,9 @@ impl<'a, A: Allocator> WriteLog<'a, A> { } /// Returns underlying allocator. - pub fn allocator(&self) -> &A { &*self.alloc } + pub fn allocator(&self) -> &A { + &*self.alloc + } pub fn alloc(&mut self, value: A::Value) -> Result { Ok(if let Some(ptr) = self.freed.pop() { @@ -210,7 +212,9 @@ impl<'a, A: Allocator> WriteLog<'a, A> { self.write_log.push((ptr, value)) } - pub fn free(&mut self, ptr: Ptr) { self.freed.push(ptr); } + pub fn free(&mut self, ptr: Ptr) { + self.freed.push(ptr); + } } impl<'a, A: Allocator> core::ops::Drop for WriteLog<'a, A> { @@ -241,7 +245,9 @@ pub mod test_utils { Self { count: 0, pool, free_list: Default::default() } } - pub fn count(&self) -> usize { self.count } + pub fn count(&self) -> usize { + self.count + } /// Gets index in the memory pool for the given pointer. /// diff --git a/common/proto-utils/src/lib.rs b/common/proto-utils/src/lib.rs index 28a912fc..ede0ac90 100644 --- a/common/proto-utils/src/lib.rs +++ b/common/proto-utils/src/lib.rs @@ -35,7 +35,6 @@ pub trait AnyConvert: Sized { fn try_from_any(type_url: &str, value: &[u8]) -> Result; } - /// Error during decoding of a protocol message. #[derive(Clone, PartialEq, Eq, derive_more::From)] pub enum DecodeError { @@ -64,7 +63,9 @@ pub enum DecodeError { pub struct BadMessage; impl From for DecodeError { - fn from(_: BadMessage) -> Self { Self::BadMessage } + fn from(_: BadMessage) -> Self { + Self::BadMessage + } } impl core::fmt::Debug for DecodeError { @@ -106,7 +107,6 @@ impl From for ibc_core_client_context::types::error::ClientError { } } - /// Defines common associated symbols and conversions for a proto message type. #[macro_export] macro_rules! define_message { @@ -230,7 +230,6 @@ macro_rules! define_message { }; } - /// Implements conversion between given type and Any message. /// /// Specified type must implement [`AnyConvert`]. @@ -281,7 +280,6 @@ macro_rules! impl_from_to_any { }; } - /// Defines a wrapper type for a raw protocol message type. // TODO(mina86): Add definition of tests. #[macro_export] diff --git a/common/proto-utils/src/tests.rs b/common/proto-utils/src/tests.rs index 19c5ec69..863deb6a 100644 --- a/common/proto-utils/src/tests.rs +++ b/common/proto-utils/src/tests.rs @@ -10,9 +10,13 @@ pub mod pb { const NAME: &'static str = "Message"; const PACKAGE: &'static str = "foo"; - fn full_name() -> ::alloc::string::String { "foo.Message".into() } + fn full_name() -> ::alloc::string::String { + "foo.Message".into() + } - fn type_url() -> ::alloc::string::String { "/foo.Message".into() } + fn type_url() -> ::alloc::string::String { + "/foo.Message".into() + } } } } diff --git a/common/sealable-trie/src/bits.rs b/common/sealable-trie/src/bits.rs index dbf016c5..7a3ff841 100644 --- a/common/sealable-trie/src/bits.rs +++ b/common/sealable-trie/src/bits.rs @@ -107,19 +107,23 @@ impl<'a> Slice<'a> { let used = slice.bytes(); let first = used.first().copied().unwrap_or_default(); let last = used.last().copied().unwrap_or_default(); - (first & !front) == 0 && - (last & !back) == 0 && - bytes[used.len()..].iter().all(|&b| b == 0) + (first & !front) == 0 + && (last & !back) == 0 + && bytes[used.len()..].iter().all(|&b| b == 0) }) } /// Returns length of the slice in bits. #[inline] - pub fn len(&self) -> u16 { self.length } + pub fn len(&self) -> u16 { + self.length + } /// Returns whether the slice is empty. #[inline] - pub fn is_empty(&self) -> bool { self.length == 0 } + pub fn is_empty(&self) -> bool { + self.length == 0 + } /// Returns the first bit in the slice advances the slice by one position. /// @@ -238,7 +242,9 @@ impl<'a> Slice<'a> { /// may be shorter than 272 bits (i.e. 34 * 8) however it will span full 34 /// bytes. #[inline] - pub fn chunks(&self) -> Chunks<'a> { Chunks::new(*self) } + pub fn chunks(&self) -> Chunks<'a> { + Chunks::new(*self) + } /// Splits slice into two at given index. /// @@ -444,7 +450,9 @@ impl<'a> Slice<'a> { /// Calculates underlying bytes length of the slice. #[inline] - fn bytes_len(&self) -> usize { bytes_len(self.offset, self.length) } + fn bytes_len(&self) -> usize { + bytes_len(self.offset, self.length) + } /// Helper method which returns masks for leading and trailing byte. /// @@ -492,7 +500,9 @@ impl From> for Owned { } impl From> for Owned { - fn from(key: ExtKey<'_>) -> Self { Self::from(Slice::from(key)) } + fn from(key: ExtKey<'_>) -> Self { + Self::from(Slice::from(key)) + } } impl Owned { @@ -517,11 +527,15 @@ impl Owned { /// Returns length of the slice in bits. #[inline] - pub fn len(&self) -> u16 { self.length } + pub fn len(&self) -> u16 { + self.length + } /// Returns whether the slice is empty. #[inline] - pub fn is_empty(&self) -> bool { self.length == 0 } + pub fn is_empty(&self) -> bool { + self.length == 0 + } /// Borrows the owned slice. pub fn as_slice(&self) -> Slice { @@ -740,30 +754,34 @@ impl core::cmp::PartialEq for Slice<'_> { if len == 1 { ((lhs[0] ^ rhs[0]) & front & back) == 0 } else { - ((lhs[0] ^ rhs[0]) & front) == 0 && - ((lhs[len - 1] ^ rhs[len - 1]) & back) == 0 && - lhs[1..len - 1] == rhs[1..len - 1] + ((lhs[0] ^ rhs[0]) & front) == 0 + && ((lhs[len - 1] ^ rhs[len - 1]) & back) == 0 + && lhs[1..len - 1] == rhs[1..len - 1] } } } impl core::cmp::PartialEq for Owned { #[inline] - fn eq(&self, other: &Self) -> bool { self.as_slice() == other.as_slice() } + fn eq(&self, other: &Self) -> bool { + self.as_slice() == other.as_slice() + } } impl core::cmp::PartialEq> for Owned { #[inline] - fn eq(&self, other: &Slice) -> bool { &self.as_slice() == other } + fn eq(&self, other: &Slice) -> bool { + &self.as_slice() == other + } } impl core::cmp::PartialEq for Slice<'_> { #[inline] - fn eq(&self, other: &Owned) -> bool { self == &other.as_slice() } + fn eq(&self, other: &Owned) -> bool { + self == &other.as_slice() + } } - - impl TryFrom> for Vec { type Error = MisalignedSlice; #[inline] @@ -795,7 +813,6 @@ impl TryFrom for Vec { } } - impl fmt::Display for Slice<'_> { fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result { use ascii::AsciiChar; diff --git a/common/sealable-trie/src/bits/concat.rs b/common/sealable-trie/src/bits/concat.rs index 48e9d7b6..7082d570 100644 --- a/common/sealable-trie/src/bits/concat.rs +++ b/common/sealable-trie/src/bits/concat.rs @@ -4,7 +4,6 @@ use lib::u3::U3; use super::{Owned, Slice}; - /// Trying to concatenate slices which result in slice whose size is too large. /// /// Slice’s length must not overflow u16. @@ -80,21 +79,23 @@ pub enum Error { } impl From for Error { - fn from(_: SliceTooLong) -> Error { Error::SliceTooLong } + fn from(_: SliceTooLong) -> Error { + Error::SliceTooLong + } } impl From for Error { - fn from(_: MisalignedSlice) -> Error { Error::Misaligned } + fn from(_: MisalignedSlice) -> Error { + Error::Misaligned + } } - pub trait Concat { type Error: Into; fn concat_impl(prefix: Self, suffix: Rhs) -> Result; } - impl<'a> Concat> for bool { type Error = SliceTooLong; @@ -215,7 +216,6 @@ pub(super) fn extend_impl( Ok(()) } - /// Checks that concatenating two slices produces slice whose length doesn’t /// overflow `u16`. pub(super) fn check_length( @@ -255,7 +255,6 @@ fn check_alignment_and_length( Ok(check_length(pre_len, suf_len)?) } - #[test] fn test_unshift() { for offset in U3::all() { diff --git a/common/sealable-trie/src/bits/ext_key.rs b/common/sealable-trie/src/bits/ext_key.rs index decdf326..4994e170 100644 --- a/common/sealable-trie/src/bits/ext_key.rs +++ b/common/sealable-trie/src/bits/ext_key.rs @@ -43,11 +43,15 @@ impl<'a> ExtKey<'a> { /// Returns length of the slice in bits. #[inline] - pub fn len(&self) -> u16 { self.0.len() } + pub fn len(&self) -> u16 { + self.0.len() + } /// Converts the object into underlying [`Slice`]. #[inline] - pub fn into_slice(self) -> Slice<'a> { self.0 } + pub fn into_slice(self) -> Slice<'a> { + self.0 + } /// Encodes key into raw binary representation. /// @@ -100,7 +104,9 @@ impl<'a> ExtKey<'a> { impl<'a> Chunks<'a> { /// Constructs a new `Chunks` iterator over given bit slice. - pub(super) fn new(slice: Slice<'a>) -> Self { Self(slice) } + pub(super) fn new(slice: Slice<'a>) -> Self { + Self(slice) + } } impl<'a> TryFrom> for ExtKey<'a> { @@ -140,8 +146,6 @@ impl fmt::Debug for Chunks<'_> { } } - - impl<'a> core::iter::Iterator for Chunks<'a> { type Item = ExtKey<'a>; diff --git a/common/sealable-trie/src/nodes.rs b/common/sealable-trie/src/nodes.rs index 517fa9d5..9ab11e17 100644 --- a/common/sealable-trie/src/nodes.rs +++ b/common/sealable-trie/src/nodes.rs @@ -245,7 +245,9 @@ impl RawNode { } /// Splits the raw byte representation in two halfs. - fn halfs(&self) -> (&[u8; 36], &[u8; 36]) { stdx::split_array_ref(&self.0) } + fn halfs(&self) -> (&[u8; 36], &[u8; 36]) { + stdx::split_array_ref(&self.0) + } /// Splits the raw byte representation in two halfs. fn halfs_mut(&mut self) -> (&mut [u8; 36], &mut [u8; 36]) { @@ -327,7 +329,9 @@ impl<'a> Reference<'a> { impl<'a, P> NodeRef<'a, P> { /// Constructs a new node reference. #[inline] - pub fn new(ptr: P, hash: &'a CryptoHash) -> Self { Self { ptr, hash } } + pub fn new(ptr: P, hash: &'a CryptoHash) -> Self { + Self { ptr, hash } + } } impl<'a, S> ValueRef<'a, S> { @@ -338,7 +342,6 @@ impl<'a, S> ValueRef<'a, S> { } } - // ============================================================================= // PartialEq diff --git a/common/sealable-trie/src/proof.rs b/common/sealable-trie/src/proof.rs index 3f573d90..a844b3ae 100644 --- a/common/sealable-trie/src/proof.rs +++ b/common/sealable-trie/src/proof.rs @@ -98,7 +98,9 @@ impl Proof { } /// Creates a builder which allows creation of proofs. - pub(crate) fn builder() -> Builder { Builder(Vec::new()) } + pub(crate) fn builder() -> Builder { + Builder(Vec::new()) + } } impl Membership { @@ -245,7 +247,9 @@ impl Item { impl Builder { /// Adds a new item to the proof. - pub fn push(&mut self, item: Item) { self.0.push(item); } + pub fn push(&mut self, item: Item) { + self.0.push(item); + } /// Reverses order of items in the builder. /// @@ -259,7 +263,9 @@ impl Builder { } /// Constructs a new membership proof from added items. - pub fn build>(self) -> T { T::from(Membership(self.0)) } + pub fn build>(self) -> T { + T::from(Membership(self.0)) + } /// Constructs a new non-membership proof from added items and given /// ‘actual’ entry. @@ -323,11 +329,17 @@ impl Builder { impl OwnedRef { /// Creates a reference pointing at node with given hash. - fn node(hash: CryptoHash) -> Self { Self { is_value: false, hash } } + fn node(hash: CryptoHash) -> Self { + Self { is_value: false, hash } + } /// Creates a reference pointing at value with given hash. - fn value(hash: CryptoHash) -> Self { Self { is_value: true, hash } } + fn value(hash: CryptoHash) -> Self { + Self { is_value: true, hash } + } /// Creates a reference pointing at given node. - fn to(node: Node) -> Self { Self::node(node.hash()) } + fn to(node: Node) -> Self { + Self::node(node.hash()) + } #[cfg(test)] #[allow(dead_code)] @@ -347,7 +359,9 @@ impl<'a, P, S> From<&'a Reference<'a, P, S>> for OwnedRef { } impl<'a, P, S> From> for OwnedRef { - fn from(rf: Reference<'a, P, S>) -> OwnedRef { Self::from(&rf) } + fn from(rf: Reference<'a, P, S>) -> OwnedRef { + Self::from(&rf) + } } impl<'a> From<&'a OwnedRef> for Reference<'a, (), ()> { diff --git a/common/sealable-trie/src/proof/serialisation.rs b/common/sealable-trie/src/proof/serialisation.rs index 031c9dcc..a3d7f664 100644 --- a/common/sealable-trie/src/proof/serialisation.rs +++ b/common/sealable-trie/src/proof/serialisation.rs @@ -286,7 +286,6 @@ fn invalid_data(msg: String) -> io::Error { io::Error::new(io::ErrorKind::InvalidData, msg) } - #[test] fn test_item_borsh() { #[track_caller] @@ -461,17 +460,19 @@ fn test_proof_borsh() { let actual = Actual::LookupKeyLeft(NonZeroU16::MIN, CryptoHash::test(1)); test(Proof::Positive(super::Membership(vec![])), &[0, 0]); - test(Proof::Positive(super::Membership(vec![item.clone()])), &[ - 1, 0, 32, 42, - ]); + test( + Proof::Positive(super::Membership(vec![item.clone()])), + &[1, 0, 32, 42], + ); test( Proof::Positive(super::Membership(vec![item.clone(), item.clone()])), &[2, 0, 32, 42, 32, 42], ); test(Proof::Negative(super::NonMembership(None, vec![])), &[0, 0x80]); - test(Proof::Negative(super::NonMembership(None, vec![item.clone()])), &[ - 1, 0x80, 32, 42, - ]); + test( + Proof::Negative(super::NonMembership(None, vec![item.clone()])), + &[1, 0x80, 32, 42], + ); #[rustfmt::skip] test( Proof::Negative(super::NonMembership( diff --git a/common/sealable-trie/src/trie.rs b/common/sealable-trie/src/trie.rs index c1b9c132..208795df 100644 --- a/common/sealable-trie/src/trie.rs +++ b/common/sealable-trie/src/trie.rs @@ -96,12 +96,16 @@ pub enum Error { impl From for Error { #[inline] - fn from(_: memory::OutOfMemory) -> Self { Self::OutOfMemory } + fn from(_: memory::OutOfMemory) -> Self { + Self::OutOfMemory + } } impl From for Error { #[inline] - fn from(err: crate::nodes::DecodeError) -> Self { Self::BadRawNode(err) } + fn from(err: crate::nodes::DecodeError) -> Self { + Self::BadRawNode(err) + } } type Result = ::core::result::Result; @@ -126,10 +130,14 @@ impl> Trie { } /// Returns hash of the root node. - pub fn hash(&self) -> &CryptoHash { &self.root_hash } + pub fn hash(&self) -> &CryptoHash { + &self.root_hash + } /// Returns whether the trie is empty. - pub fn is_empty(&self) -> bool { self.root_hash == EMPTY_TRIE_ROOT } + pub fn is_empty(&self) -> bool { + self.root_hash == EMPTY_TRIE_ROOT + } /// Deconstructs the object into the individual parts — allocator, root /// pointer and root hash. @@ -381,7 +389,6 @@ impl> Trie { } } - #[cfg(test)] impl Trie> { /// Creates a test trie using a TestAllocator with given capacity. diff --git a/common/sealable-trie/src/trie/del.rs b/common/sealable-trie/src/trie/del.rs index 2ad79f1a..1901ec5e 100644 --- a/common/sealable-trie/src/trie/del.rs +++ b/common/sealable-trie/src/trie/del.rs @@ -170,7 +170,9 @@ impl<'a, A: memory::Allocator> Context<'a, A> { } /// Frees a node. - fn del_node(&mut self, ptr: Ptr) { self.wlog.free(ptr); } + fn del_node(&mut self, ptr: Ptr) { + self.wlog.free(ptr); + } /// Converts an [`Action`] into an [`OwnedRef`] if it’s not a `Drop` action. /// diff --git a/common/sealable-trie/src/trie/tests.rs b/common/sealable-trie/src/trie/tests.rs index a9e93640..22598bae 100644 --- a/common/sealable-trie/src/trie/tests.rs +++ b/common/sealable-trie/src/trie/tests.rs @@ -162,11 +162,15 @@ fn test_seal_small() { /// Tests using `set_and_seal` to create a trie with all keys sealed. #[cfg(not(miri))] #[test] -fn test_set_and_seal() { make_trie(false, true); } +fn test_set_and_seal() { + make_trie(false, true); +} /// Tests using `set_and_seal` to create a small trie with all keys sealed. #[test] -fn test_set_and_seal_small() { make_trie(true, true); } +fn test_set_and_seal_small() { + make_trie(true, true); +} fn do_test_del((mut trie, keys): (TestTrie, &[u8]), want_mid_count: usize) { let (left, right) = keys.split_at(keys.len() / 2); @@ -183,11 +187,15 @@ fn do_test_del((mut trie, keys): (TestTrie, &[u8]), want_mid_count: usize) { /// Tests deleting all keys of a trie. #[cfg(not(miri))] #[test] -fn test_del() { do_test_del(make_trie(false, false), 8); } +fn test_del() { + do_test_del(make_trie(false, false), 8); +} /// Tests deleting all keys of a small trie. #[test] -fn test_del_small() { do_test_del(make_trie(true, false), 5); } +fn test_del_small() { + do_test_del(make_trie(true, false), 5); +} /// Tests whether deleting a node in between two Extension nodes causes the two /// Extension nodes to be rebalanced. @@ -306,10 +314,11 @@ impl<'a> KeyGen<'a> for RandKeys<'a> { Some(self.generate(known)) } - fn count(&self) -> Option { Some(self.count) } + fn count(&self) -> Option { + Some(self.count) + } } - #[test] fn stress_test() { let count = lib::test_utils::get_iteration_count(500); @@ -393,7 +402,9 @@ struct Key { } impl Key { - fn as_bytes(&self) -> &[u8] { &self.buf[..usize::from(self.len)] } + fn as_bytes(&self) -> &[u8] { + &self.buf[..usize::from(self.len)] + } } impl<'a> From<&'a [u8]> for Key { @@ -410,20 +421,28 @@ impl<'a> From<&'a [u8]> for Key { } impl<'a> From<&'a str> for Key { - fn from(key: &'a str) -> Self { Self::from(key.as_bytes()) } + fn from(key: &'a str) -> Self { + Self::from(key.as_bytes()) + } } impl core::ops::Deref for Key { type Target = [u8]; - fn deref(&self) -> &[u8] { self.as_bytes() } + fn deref(&self) -> &[u8] { + self.as_bytes() + } } impl alloc::borrow::Borrow<[u8]> for Key { - fn borrow(&self) -> &[u8] { self.as_bytes() } + fn borrow(&self) -> &[u8] { + self.as_bytes() + } } impl core::cmp::PartialEq for Key { - fn eq(&self, other: &Self) -> bool { self.as_bytes() == other.as_bytes() } + fn eq(&self, other: &Self) -> bool { + self.as_bytes() == other.as_bytes() + } } impl core::cmp::PartialOrd for Key { @@ -444,7 +463,6 @@ impl core::fmt::Debug for Key { } } - trait KeyGen<'a> { fn next(&mut self, known: &HashMap) -> Option<&'a [u8]>; fn count(&self) -> Option; @@ -454,23 +472,28 @@ impl<'a, 'b, T: KeyGen<'b>> KeyGen<'b> for &'a mut T { fn next(&mut self, known: &HashMap) -> Option<&'b [u8]> { (**self).next(known) } - fn count(&self) -> Option { (**self).count() } + fn count(&self) -> Option { + (**self).count() + } } struct IterKeyGen(I); impl<'a, I: Iterator> IterKeyGen { - fn new(it: impl IntoIterator) -> Self { Self(it.into_iter()) } + fn new(it: impl IntoIterator) -> Self { + Self(it.into_iter()) + } } impl<'a, I: Iterator> KeyGen<'a> for IterKeyGen { fn next(&mut self, _known: &HashMap) -> Option<&'a [u8]> { self.0.next() } - fn count(&self) -> Option { self.0.size_hint().1 } + fn count(&self) -> Option { + self.0.size_hint().1 + } } - struct TestTrie { trie: super::Trie>, mapping: HashMap, @@ -486,7 +509,9 @@ impl TestTrie { } } - pub fn hash(&self) -> &CryptoHash { self.trie.hash() } + pub fn hash(&self) -> &CryptoHash { + self.trie.hash() + } pub fn is_empty(&self) -> bool { if self.trie.is_empty() { @@ -497,7 +522,9 @@ impl TestTrie { } } - pub fn nodes_count(&self) -> usize { self.trie.alloc.count() } + pub fn nodes_count(&self) -> usize { + self.trie.alloc.count() + } pub fn set(&mut self, key: &[u8], verbose: bool) { self.try_set(key, verbose).unwrap(); diff --git a/common/trie-ids/src/ids.rs b/common/trie-ids/src/ids.rs index 55da8f33..2b54414a 100644 --- a/common/trie-ids/src/ids.rs +++ b/common/trie-ids/src/ids.rs @@ -84,7 +84,9 @@ impl<'a> TryFrom<&'a ibc::ClientId> for ClientIdx { impl PartialEq for ClientIdx { #[inline] - fn eq(&self, rhs: &usize) -> bool { usize::from(*self) == *rhs } + fn eq(&self, rhs: &usize) -> bool { + usize::from(*self) == *rhs + } } // ==== Connection Id ========================================================== @@ -148,12 +150,16 @@ impl TryFrom<&ibc::ConnectionId> for ConnectionIdx { impl From for ibc::ConnectionId { #[inline] - fn from(idx: ConnectionIdx) -> Self { Self::new(u64::from(idx)) } + fn from(idx: ConnectionIdx) -> Self { + Self::new(u64::from(idx)) + } } impl From<&ConnectionIdx> for ibc::ConnectionId { #[inline] - fn from(idx: &ConnectionIdx) -> Self { Self::new(u64::from(*idx)) } + fn from(idx: &ConnectionIdx) -> Self { + Self::new(u64::from(*idx)) + } } impl fmt::Debug for ConnectionIdx { @@ -225,12 +231,16 @@ impl TryFrom<&ibc::ChannelId> for ChannelIdx { impl From for ibc::ChannelId { #[inline] - fn from(idx: ChannelIdx) -> Self { Self::new(u64::from(idx)) } + fn from(idx: ChannelIdx) -> Self { + Self::new(u64::from(idx)) + } } impl From<&ChannelIdx> for ibc::ChannelId { #[inline] - fn from(idx: &ChannelIdx) -> Self { Self::new(u64::from(*idx)) } + fn from(idx: &ChannelIdx) -> Self { + Self::new(u64::from(*idx)) + } } impl fmt::Debug for ChannelIdx { @@ -267,7 +277,9 @@ impl PortKey { /// Borrows the type as underlying byte array. #[inline] - pub fn as_bytes(&self) -> &[u8; 9] { &self.0 } + pub fn as_bytes(&self) -> &[u8; 9] { + &self.0 + } /// Formats the port identifier in the buffer and returns reference to it as /// a string. @@ -327,7 +339,9 @@ impl TryFrom<&ibc::PortId> for PortKey { } impl From for ibc::PortId { - fn from(port_key: PortKey) -> Self { Self::from(&port_key) } + fn from(port_key: PortKey) -> Self { + Self::from(&port_key) + } } impl From<&PortKey> for ibc::PortId { @@ -422,7 +436,9 @@ impl PortChannelPK { }) } - pub fn port_id(&self) -> ibc::PortId { ibc::PortId::from(&self.port_key) } + pub fn port_id(&self) -> ibc::PortId { + ibc::PortId::from(&self.port_key) + } pub fn channel_id(&self) -> ibc::ChannelId { ibc::ChannelId::new(self.channel_idx.into()) @@ -435,13 +451,21 @@ pub trait MaybeOwned { } impl MaybeOwned for &T { - fn as_ref(&self) -> &T { self } - fn into_owned(self) -> T { (*self).clone() } + fn as_ref(&self) -> &T { + self + } + fn into_owned(self) -> T { + (*self).clone() + } } impl MaybeOwned for T { - fn as_ref(&self) -> &T { self } - fn into_owned(self) -> T { self } + fn as_ref(&self) -> &T { + self + } + fn into_owned(self) -> T { + self + } } // ==== Counter (inetrnal) ===================================================== @@ -501,7 +525,9 @@ impl Counter { impl From for usize { #[inline] - fn from(cnt: Counter) -> usize { cnt.0 as usize } + fn from(cnt: Counter) -> usize { + cnt.0 as usize + } } impl core::fmt::Debug for Counter { diff --git a/common/trie-ids/src/path_info.rs b/common/trie-ids/src/path_info.rs index 7637b54b..d9f3f76b 100644 --- a/common/trie-ids/src/path_info.rs +++ b/common/trie-ids/src/path_info.rs @@ -40,7 +40,9 @@ pub enum SequenceKind { } impl From for usize { - fn from(kind: SequenceKind) -> usize { kind as usize } + fn from(kind: SequenceKind) -> usize { + kind as usize + } } /// Error when converting IBC path into a trie key. @@ -227,7 +229,6 @@ impl PathInfo { } } - #[test] fn test_try_from_path() { use std::str::FromStr; diff --git a/common/trie-ids/src/trie_key.rs b/common/trie-ids/src/trie_key.rs index 3af358af..41d4fdbd 100644 --- a/common/trie-ids/src/trie_key.rs +++ b/common/trie-ids/src/trie_key.rs @@ -1,7 +1,6 @@ use super::path::SequencePath; use super::{ibc, ids}; - /// A key used for indexing entries in the provable storage. /// /// The key is built from IBC storage paths. The first byte is a tag (see @@ -50,7 +49,9 @@ pub enum Tag { } impl From for u8 { - fn from(tag: Tag) -> u8 { tag as u8 } + fn from(tag: Tag) -> u8 { + tag as u8 + } } /// A discriminant used to distinguish client state and consensus state upgrade @@ -63,7 +64,9 @@ enum UpgradeType { } impl From for u8 { - fn from(ty: UpgradeType) -> u8 { ty as u8 } + fn from(ty: UpgradeType) -> u8 { + ty as u8 + } } impl TrieKey { @@ -183,7 +186,9 @@ impl TrieKey { impl core::ops::Deref for TrieKey { type Target = [u8]; - fn deref(&self) -> &[u8] { &self.bytes[..usize::from(self.len)] } + fn deref(&self) -> &[u8] { + &self.bytes[..usize::from(self.len)] + } } impl core::fmt::Display for TrieKey { @@ -277,7 +282,6 @@ impl From for TrieKey { } } - /// Component of a [`TrieKey`]. /// /// A `TrieKey` is constructed by concatenating a sequence of components. @@ -352,12 +356,16 @@ impl AsComponent for UpgradeType { impl AsComponent for [u8; N] { #[inline] - fn append_into(&self, dest: &mut TrieKey) { dest.extend(self); } + fn append_into(&self, dest: &mut TrieKey) { + dest.extend(self); + } } impl AsComponent for &T { #[inline] - fn append_into(&self, dest: &mut TrieKey) { (*self).append_into(dest) } + fn append_into(&self, dest: &mut TrieKey) { + (*self).append_into(dest) + } } impl AsComponent for (T, U) { @@ -368,7 +376,6 @@ impl AsComponent for (T, U) { } } - #[test] fn test_encoding() { use std::str::FromStr; diff --git a/common/wasm/src/consensus_state.rs b/common/wasm/src/consensus_state.rs index 3623319d..ebfef7cd 100644 --- a/common/wasm/src/consensus_state.rs +++ b/common/wasm/src/consensus_state.rs @@ -40,7 +40,9 @@ impl From for proto::ConsensusState { } impl From<&ConsensusState> for proto::ConsensusState { - fn from(state: &ConsensusState) -> Self { Self::from(state.clone()) } + fn from(state: &ConsensusState) -> Self { + Self::from(state.clone()) + } } impl TryFrom for ConsensusState { diff --git a/solana/allocator/src/lib.rs b/solana/allocator/src/lib.rs index c69b426f..ff5f01dd 100644 --- a/solana/allocator/src/lib.rs +++ b/solana/allocator/src/lib.rs @@ -142,7 +142,9 @@ impl BumpAllocator { /// /// Note that by default `G` is a unit type which means that there is no /// reserved global state. - pub fn global(&self) -> &G { &self.header().global } + pub fn global(&self) -> &G { + &self.header().global + } } unsafe impl GlobalAlloc for BumpAllocator { diff --git a/solana/allocator/src/ptr.rs b/solana/allocator/src/ptr.rs index f612726b..d10899df 100644 --- a/solana/allocator/src/ptr.rs +++ b/solana/allocator/src/ptr.rs @@ -26,7 +26,6 @@ pub(super) fn range(start: *mut u8, size: usize) -> core::ops::Range<*mut u8> { start..start.wrapping_add(size) } - /// Copies `size` bytes from `src` to `dst`. /// /// # Safety diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index bce904e0..89e1dcb3 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -61,33 +61,6 @@ pub mod bridge_escrow { Ok(()) } - /// Transfers funds from the auctioneer's escrow account to a specified recipient. - /// - /// The funds are stored in a token account owned by the auctioneer state PDA. - pub fn auctioneer_transfer(ctx: Context, amount: u64) -> Result<()> { - // Transfer SPL tokens from the auctioneer's escrow account to the recipient's account - let cpi_accounts = SplTransfer { - from: ctx.accounts.escrow_token_account.to_account_info(), - to: ctx.accounts.recipient_token_account.to_account_info(), - authority: ctx.accounts.auctioneer_state.to_account_info(), - }; - - let cpi_program = ctx.accounts.token_program.to_account_info(); - - // Retrieve the bump seed using the `seeds` provided in the context - let auctioneer_seeds = &[ - AUCTIONEER_SEED.as_ref(), - &[ctx.bumps.auctioneer_state] - ]; - let signer_seeds = &[&auctioneer_seeds[..]]; - - let cpi_ctx = CpiContext::new_with_signer(cpi_program, cpi_accounts, signer_seeds); - - token::transfer(cpi_ctx, amount)?; - - Ok(()) - } - /// Called by the auctioneer whose address is stored in `auctioneer` state account. pub fn store_intent( ctx: Context, @@ -179,9 +152,10 @@ pub mod bridge_escrow { let token_program = &ctx.accounts.token_program; let solver = &ctx.accounts.solver; - let amount_out = intent.amount_out.parse::().map_err(|_| { - ErrorCode::InvalidAmount - })?; + let amount_out = intent + .amount_out + .parse::() + .map_err(|_| ErrorCode::InvalidAmount)?; // Transfer tokens from Solver to User let cpi_accounts = SplTransfer { @@ -593,15 +567,3 @@ pub enum ErrorCode { #[msg("Invalid hashed full denom")] InvalidHashedFullDenom, } - -#[derive(Accounts)] -pub struct AuctioneerTransfer<'info> { - #[account(seeds = [AUCTIONEER_SEED], bump)] - pub auctioneer_state: Account<'info, Auctioneer>, // The PDA representing the auctioneer's state - #[account(mut, token::authority = auctioneer_state)] - pub escrow_token_account: Account<'info, TokenAccount>, // PDA's token account holding escrowed funds - #[account(mut)] - pub recipient_token_account: Account<'info, TokenAccount>, // Recipient's token account - pub token_program: Program<'info, Token>, // Token program reference -} - diff --git a/solana/restaking/programs/restaking/src/lib.rs b/solana/restaking/programs/restaking/src/lib.rs index 717fc5f2..0136a217 100644 --- a/solana/restaking/programs/restaking/src/lib.rs +++ b/solana/restaking/programs/restaking/src/lib.rs @@ -305,14 +305,14 @@ pub mod restaking { return Err(error!(ErrorCodes::InvalidWithdrawer)); } - if ctx.accounts.withdrawer_token_account.key() != - withdrawal_request_params.token_account + if ctx.accounts.withdrawer_token_account.key() + != withdrawal_request_params.token_account { return Err(error!(ErrorCodes::InvalidTokenAccount)); }; - let unbonding_period = withdrawal_request_params.timestamp_in_sec + - UNBONDING_PERIOD_IN_SEC; + let unbonding_period = withdrawal_request_params.timestamp_in_sec + + UNBONDING_PERIOD_IN_SEC; let current_timestamp = Clock::get()?.unix_timestamp as u64; msg!( diff --git a/solana/restaking/programs/restaking/src/token.rs b/solana/restaking/programs/restaking/src/token.rs index 3c7bfc1a..c547bb3a 100644 --- a/solana/restaking/programs/restaking/src/token.rs +++ b/solana/restaking/programs/restaking/src/token.rs @@ -49,11 +49,14 @@ pub fn transfer( /// we dont need signed invocation. pub fn mint_nft(accounts: MintNftAccounts<'_>) -> Result<()> { mint_to( - CpiContext::new(accounts.token_program.clone(), MintTo { - authority: accounts.mint_authority.clone(), - to: accounts.to, - mint: accounts.token_mint.clone(), - }), + CpiContext::new( + accounts.token_program.clone(), + MintTo { + authority: accounts.mint_authority.clone(), + to: accounts.to, + mint: accounts.token_mint.clone(), + }, + ), 1, // 1 token )?; @@ -87,17 +90,20 @@ pub fn mint_nft(accounts: MintNftAccounts<'_>) -> Result<()> { msg!("Run create master edition v3"); create_master_edition_v3( - CpiContext::new(accounts.metadata_program, CreateMasterEditionV3 { - edition: accounts.edition, - mint: accounts.token_mint, - update_authority: accounts.update_authority, - mint_authority: accounts.mint_authority, - payer: accounts.payer, - metadata: accounts.metadata, - token_program: accounts.token_program, - system_program: accounts.system_program, - rent: accounts.rent, - }), + CpiContext::new( + accounts.metadata_program, + CreateMasterEditionV3 { + edition: accounts.edition, + mint: accounts.token_mint, + update_authority: accounts.update_authority, + mint_authority: accounts.mint_authority, + payer: accounts.payer, + metadata: accounts.metadata, + token_program: accounts.token_program, + system_program: accounts.system_program, + rent: accounts.rent, + }, + ), Some(1), )?; Ok(()) diff --git a/solana/signature-verifier/src/api.rs b/solana/signature-verifier/src/api.rs index aaf64e1b..6b1d1883 100644 --- a/solana/signature-verifier/src/api.rs +++ b/solana/signature-verifier/src/api.rs @@ -4,7 +4,6 @@ use solana_program::pubkey::Pubkey; type Result = core::result::Result; - /// A signature hash as stored in the [`SignaturesAccount`]. /// /// When the signature verifier program confirms that a signature has been @@ -56,7 +55,9 @@ impl SignatureHash { } impl AsRef<[u8; 32]> for SignatureHash { - fn as_ref(&self) -> &[u8; 32] { &self.0 } + fn as_ref(&self) -> &[u8; 32] { + &self.0 + } } impl<'a> From> for SignatureHash { @@ -73,7 +74,6 @@ impl<'a> From<&crate::ed25519_program::Entry<'a>> for SignatureHash { } } - /// Wrapper around signatures account created by the verifier program. #[derive(Clone, Copy, derive_more::Deref, derive_more::DerefMut)] pub struct SignaturesAccount<'a, 'info>(pub(crate) &'a AccountInfo<'info>); @@ -201,7 +201,6 @@ pub(crate) fn find_sighash( // .map(SignatureHash::wrap_ref)) // } - #[test] fn test_ed25519() { let sig1 = SignatureHash::new_ed25519(&[11; 32], &[12; 64], b"foo"); diff --git a/solana/signature-verifier/src/ed25519.rs b/solana/signature-verifier/src/ed25519.rs index 9b40c5ce..76413c6b 100644 --- a/solana/signature-verifier/src/ed25519.rs +++ b/solana/signature-verifier/src/ed25519.rs @@ -42,7 +42,9 @@ impl From for PubKey { } impl From for solana_program::pubkey::Pubkey { - fn from(pubkey: PubKey) -> Self { Self::from(pubkey.0) } + fn from(pubkey: PubKey) -> Self { + Self::from(pubkey.0) + } } impl PartialEq for PubKey { @@ -52,7 +54,9 @@ impl PartialEq for PubKey { } impl PartialEq for solana_program::pubkey::Pubkey { - fn eq(&self, other: &PubKey) -> bool { self.as_ref() == &other.0[..] } + fn eq(&self, other: &PubKey) -> bool { + self.as_ref() == &other.0[..] + } } #[cfg(feature = "guest")] @@ -60,7 +64,9 @@ impl guestchain::PubKey for PubKey { type Signature = Signature; #[inline] - fn as_bytes(&self) -> alloc::borrow::Cow<'_, [u8]> { (&self.0[..]).into() } + fn as_bytes(&self) -> alloc::borrow::Cow<'_, [u8]> { + (&self.0[..]).into() + } #[inline] fn from_bytes(bytes: &[u8]) -> Result { Ok(Self(bytes.try_into()?)) @@ -102,7 +108,9 @@ impl<'a> TryFrom<&'a [u8]> for &'a Signature { #[cfg(feature = "guest")] impl guestchain::Signature for Signature { #[inline] - fn as_bytes(&self) -> alloc::borrow::Cow<'_, [u8]> { (&self.0[..]).into() } + fn as_bytes(&self) -> alloc::borrow::Cow<'_, [u8]> { + (&self.0[..]).into() + } #[inline] fn from_bytes(bytes: &[u8]) -> Result { Ok(Self(bytes.try_into()?)) diff --git a/solana/signature-verifier/src/ed25519_program.rs b/solana/signature-verifier/src/ed25519_program.rs index 269eeac7..90642fe7 100644 --- a/solana/signature-verifier/src/ed25519_program.rs +++ b/solana/signature-verifier/src/ed25519_program.rs @@ -145,7 +145,6 @@ fn write_slice(dst: &mut [MaybeUninit], src: &[u8]) { dst.copy_from_slice(src) } - /// Creates a new iterator over signatures in given Ed25519 native program /// instruction data. /// @@ -220,15 +219,21 @@ pub enum Error { pub struct BadData; impl From for Error { - fn from(_: BadData) -> Self { Self::BadData } + fn from(_: BadData) -> Self { + Self::BadData + } } impl From for solana_program::program_error::ProgramError { - fn from(_: BadData) -> Self { Self::InvalidInstructionData } + fn from(_: BadData) -> Self { + Self::InvalidInstructionData + } } impl From for solana_program::program_error::ProgramError { - fn from(_: Error) -> Self { Self::InvalidInstructionData } + fn from(_: Error) -> Self { + Self::InvalidInstructionData + } } /// An item returned by th @@ -248,9 +253,9 @@ fn decode_entry<'a>(data: &'a [u8], entry: &'a [u8; 14]) -> Item<'a> { let [sig_offset, sig_ix_idx, key_offset, key_ix_idx, msg_offset, msg_size, msg_ix_idx] = entry; - if sig_ix_idx != u16::MAX || - key_ix_idx != u16::MAX || - msg_ix_idx != u16::MAX + if sig_ix_idx != u16::MAX + || key_ix_idx != u16::MAX + || msg_ix_idx != u16::MAX { return Err(Error::UnsupportedFeature); } @@ -293,12 +298,18 @@ impl<'a> core::iter::Iterator for Iter<'a> { Some(decode_entry(self.data, entry)) } - fn size_hint(&self) -> (usize, Option) { self.entries.size_hint() } - fn count(self) -> usize { self.entries.count() } + fn size_hint(&self) -> (usize, Option) { + self.entries.size_hint() + } + fn count(self) -> usize { + self.entries.count() + } } impl<'a> core::iter::ExactSizeIterator for Iter<'a> { - fn len(&self) -> usize { self.entries.len() } + fn len(&self) -> usize { + self.entries.len() + } } impl<'a> core::iter::DoubleEndedIterator for Iter<'a> { diff --git a/solana/signature-verifier/src/program.rs b/solana/signature-verifier/src/program.rs index 9335bc74..20e8079b 100644 --- a/solana/signature-verifier/src/program.rs +++ b/solana/signature-verifier/src/program.rs @@ -91,7 +91,6 @@ fn process_instruction<'a>( } } - /// Handles the Update operation. fn handle_update( ctx: Context, @@ -134,7 +133,6 @@ fn handle_update( ctx.signatures.write_count_and_sort(count) } - /// Extracts signatures from a call to Ed25519 native program. /// /// If the `instruction` doesn’t correspond to call to the Ed25519 signature @@ -307,7 +305,6 @@ impl<'a, 'info> Context<'a, 'info> { } } - /// Reads given object from the start of the slice advancing it. /// /// Returns an error if slice is too short. diff --git a/solana/signature-verifier/src/verifier.rs b/solana/signature-verifier/src/verifier.rs index ea5c2546..0e628d3f 100644 --- a/solana/signature-verifier/src/verifier.rs +++ b/solana/signature-verifier/src/verifier.rs @@ -55,7 +55,9 @@ impl<'info> Default for Verifier<'info> { /// sigverify program (see [`Self::set_sigverify_account`]). Unless at /// least on of those is initialised, the verifier will reject all /// signatures. - fn default() -> Self { Self { ed25519_data: None, sigverify_data: None } } + fn default() -> Self { + Self { ed25519_data: None, sigverify_data: None } + } } impl<'info> Verifier<'info> { @@ -161,7 +163,9 @@ fn check_sigverify_data(data: &[u8], entry: &Entry) -> Result { } impl From for Error { - fn from(_: crate::ed25519_program::BadData) -> Self { Self::BadData } + fn from(_: crate::ed25519_program::BadData) -> Self { + Self::BadData + } } impl From for ProgramError { diff --git a/solana/solana-ibc/programs/solana-ibc/src/allocator.rs b/solana/solana-ibc/programs/solana-ibc/src/allocator.rs index e1c1122c..9b387593 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/allocator.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/allocator.rs @@ -66,7 +66,9 @@ mod imp { }; /// Returns reference to the global state. - pub(crate) fn global() -> &'static Global { ALLOCATOR.global() } + pub(crate) fn global() -> &'static Global { + ALLOCATOR.global() + } } #[cfg(any( diff --git a/solana/solana-ibc/programs/solana-ibc/src/chain.rs b/solana/solana-ibc/programs/solana-ibc/src/chain.rs index 24fda8fe..5e81f7b0 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/chain.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/chain.rs @@ -427,15 +427,21 @@ fn get_host_head() -> Result<(guestchain::HostHeight, NonZeroU64)> { } impl From for Error { - fn from(_: ChainNotInitialised) -> Self { Error::ChainNotInitialised } + fn from(_: ChainNotInitialised) -> Self { + Error::ChainNotInitialised + } } impl From for anchor_lang::error::AnchorError { - fn from(err: ChainNotInitialised) -> Self { Error::from(err).into() } + fn from(err: ChainNotInitialised) -> Self { + Error::from(err).into() + } } impl From for anchor_lang::error::Error { - fn from(err: ChainNotInitialised) -> Self { Error::from(err).into() } + fn from(err: ChainNotInitialised) -> Self { + Error::from(err).into() + } } impl From for ibc::ClientError { diff --git a/solana/solana-ibc/programs/solana-ibc/src/client_state/impls.rs b/solana/solana-ibc/programs/solana-ibc/src/client_state/impls.rs index 3a9357f5..40d5d920 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/client_state/impls.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/client_state/impls.rs @@ -232,7 +232,9 @@ mod tm { ProvidedVotingPowerCalculator, ProdCommitValidator, >; - fn verifier(&self) -> Self::Verifier { Default::default() } + fn verifier(&self) -> Self::Verifier { + Default::default() + } } impl VerificationPredicates for InnerProdPredicates { @@ -289,11 +291,21 @@ impl ibc::HostFunctionsProvider for SolanaHostFunctions { unimplemented!() } - fn sha2_512(_message: &[u8]) -> [u8; 64] { unimplemented!() } - fn sha2_512_truncated(_message: &[u8]) -> [u8; 32] { unimplemented!() } - fn ripemd160(_message: &[u8]) -> [u8; 20] { unimplemented!() } - fn blake2b_512(_message: &[u8]) -> [u8; 64] { unimplemented!() } - fn blake2s_256(_message: &[u8]) -> [u8; 32] { unimplemented!() } + fn sha2_512(_message: &[u8]) -> [u8; 64] { + unimplemented!() + } + fn sha2_512_truncated(_message: &[u8]) -> [u8; 32] { + unimplemented!() + } + fn ripemd160(_message: &[u8]) -> [u8; 20] { + unimplemented!() + } + fn blake2b_512(_message: &[u8]) -> [u8; 64] { + unimplemented!() + } + fn blake2s_256(_message: &[u8]) -> [u8; 32] { + unimplemented!() + } } #[cfg(all(test, not(miri)))] diff --git a/solana/solana-ibc/programs/solana-ibc/src/consensus_state.rs b/solana/solana-ibc/programs/solana-ibc/src/consensus_state.rs index 46f3d4b3..fb228367 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/consensus_state.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/consensus_state.rs @@ -112,7 +112,6 @@ impl AnyConsensusState { } } - impl From for AnyConsensusState { fn from(state: ibc::tm::types::ConsensusState) -> Self { Self::Tendermint(state.into()) diff --git a/solana/solana-ibc/programs/solana-ibc/src/error.rs b/solana/solana-ibc/programs/solana-ibc/src/error.rs index 3a92019e..6079ab3b 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/error.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/error.rs @@ -132,10 +132,12 @@ pub enum Error { } impl Error { - pub fn name(&self) -> String { <&'static str>::from(self).into() } + pub fn name(&self) -> String { + <&'static str>::from(self).into() + } pub fn code(&self) -> u32 { - anchor_lang::error::ERROR_CODE_OFFSET + - ErrorDiscriminants::from(self) as u32 + anchor_lang::error::ERROR_CODE_OFFSET + + ErrorDiscriminants::from(self) as u32 } } @@ -151,15 +153,21 @@ impl core::fmt::Display for Error { } impl From for u32 { - fn from(err: Error) -> u32 { err.code() } + fn from(err: Error) -> u32 { + err.code() + } } impl From<&Error> for u32 { - fn from(err: &Error) -> u32 { err.code() } + fn from(err: &Error) -> u32 { + err.code() + } } impl From for Error { - fn from(_: manager::BadGenesis) -> Self { Self::Internal("BadGenesis") } + fn from(_: manager::BadGenesis) -> Self { + Self::Internal("BadGenesis") + } } impl From for Error { diff --git a/solana/solana-ibc/programs/solana-ibc/src/events.rs b/solana/solana-ibc/programs/solana-ibc/src/events.rs index 5adb28ce..d1a6090f 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/events.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/events.rs @@ -147,7 +147,6 @@ pub fn emit<'a>(event: impl Into>) -> Result<(), String> { event.into().emit() } - /// Defines Copy-on-Write wrapper for specified type. /// /// Due to limited interface of the [`alloc::borrow::Cow`] type, we need @@ -240,7 +239,6 @@ pub fn bytes(value: &[u8]) -> alloc::borrow::Cow<'_, [u8]> { alloc::borrow::Cow::Borrowed(value) } - #[cfg(test)] // insta uses open to read the snapshot file which is not available when running // through Miri. diff --git a/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs b/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs index 57087833..50e828a9 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs @@ -118,13 +118,14 @@ impl IbcStorage<'_, '_> { } } - impl ibc::ExecutionContext for IbcStorage<'_, '_> { /// Does nothing in the current implementation. /// /// The clients are stored in the vector so we can easily find how many /// clients were created. So thats why this method doesnt do anything. - fn increase_client_counter(&mut self) -> Result { Ok(()) } + fn increase_client_counter(&mut self) -> Result { + Ok(()) + } fn store_connection( &mut self, @@ -177,7 +178,9 @@ impl ibc::ExecutionContext for IbcStorage<'_, '_> { /// /// Connections are stored in a vector in an order, so the length of the /// array specifies the number of connections. - fn increase_connection_counter(&mut self) -> Result { Ok(()) } + fn increase_connection_counter(&mut self) -> Result { + Ok(()) + } fn store_packet_commitment( &mut self, @@ -297,7 +300,9 @@ impl ibc::ExecutionContext for IbcStorage<'_, '_> { Ok(()) } - fn get_client_execution_context(&mut self) -> &mut Self::E { self } + fn get_client_execution_context(&mut self) -> &mut Self::E { + self + } } impl storage::IbcStorage<'_, '_> { diff --git a/solana/solana-ibc/programs/solana-ibc/src/ix_data_account.rs b/solana/solana-ibc/programs/solana-ibc/src/ix_data_account.rs index 27119034..51cf7a65 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/ix_data_account.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/ix_data_account.rs @@ -73,7 +73,9 @@ use solana_program::pubkey::Pubkey; pub struct Accounts(T, Pubkey); impl Accounts { - pub fn new(accounts: T, ix_data: Pubkey) -> Self { Self(accounts, ix_data) } + pub fn new(accounts: T, ix_data: Pubkey) -> Self { + Self(accounts, ix_data) + } } /// An ‘instruction’ which instructs smart contract to read the data from an @@ -115,21 +117,26 @@ pub(crate) fn get_ix_data<'a>( impl anchor_lang::Discriminator for Instruction { const DISCRIMINATOR: [u8; 8] = [0; 8]; - fn discriminator() -> [u8; 8] { panic!() } + fn discriminator() -> [u8; 8] { + panic!() + } } impl borsh::BorshSerialize for Instruction { fn serialize(&self, _writer: &mut W) -> io::Result<()> { Ok(()) } - fn try_to_vec(&self) -> io::Result> { Ok(Vec::new()) } + fn try_to_vec(&self) -> io::Result> { + Ok(Vec::new()) + } } impl anchor_lang::InstructionData for Instruction { - fn data(&self) -> Vec { Vec::new() } + fn data(&self) -> Vec { + Vec::new() + } } - #[test] fn test_get_ix_data() { assert_eq!( diff --git a/solana/solana-ibc/programs/solana-ibc/src/lib.rs b/solana/solana-ibc/programs/solana-ibc/src/lib.rs index f284173e..a1b2e80d 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/lib.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/lib.rs @@ -284,8 +284,8 @@ pub mod solana_ibc { ) -> Result<()> { let fee_account = &ctx.accounts.fee_account; let minimum_balance = Rent::get()? - .minimum_balance(fee_account.data_len()) + - MINIMUM_FEE_ACCOUNT_BALANCE; + .minimum_balance(fee_account.data_len()) + + MINIMUM_FEE_ACCOUNT_BALANCE; let mut available_balance = fee_account.try_borrow_mut_lamports()?; if **available_balance > minimum_balance { **ctx.accounts.fee_collector.try_borrow_mut_lamports()? += @@ -321,10 +321,13 @@ pub mod solana_ibc { } if !private_storage.assets.contains_key(&hashed_full_denom) { - private_storage.assets.insert(hashed_full_denom, storage::Asset { - original_decimals, - effective_decimals_on_sol: effective_decimals, - }); + private_storage.assets.insert( + hashed_full_denom, + storage::Asset { + original_decimals, + effective_decimals_on_sol: effective_decimals, + }, + ); } else { return Err(error!(error::Error::AssetAlreadyExists)); } @@ -451,8 +454,8 @@ pub mod solana_ibc { let mut token_ctx = store.clone(); // Check if atleast one of the timeouts is non zero. - if !msg.timeout_height_on_b.is_set() && - !msg.timeout_timestamp_on_b.is_set() + if !msg.timeout_height_on_b.is_set() + && !msg.timeout_timestamp_on_b.is_set() { return Err(error::Error::InvalidTimeout.into()); } diff --git a/solana/solana-ibc/programs/solana-ibc/src/mocks.rs b/solana/solana-ibc/programs/solana-ibc/src/mocks.rs index 53489f09..a0014c84 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/mocks.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/mocks.rs @@ -3,7 +3,6 @@ use anchor_lang::prelude::*; use crate::ibc::ExecutionContext; use crate::{ibc, storage, MockDeliver}; - pub(crate) fn mock_deliver<'a, 'info>( ctx: Context<'a, 'a, 'a, 'info, MockDeliver<'info>>, port_id: ibc::PortId, @@ -78,7 +77,6 @@ pub(crate) fn mock_deliver<'a, 'info>( ) .unwrap(); - // For Client on Chain A store .store_connection( diff --git a/solana/solana-ibc/programs/solana-ibc/src/storage.rs b/solana/solana-ibc/programs/solana-ibc/src/storage.rs index a57fac5c..eb71c5cc 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/storage.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/storage.rs @@ -217,7 +217,9 @@ pub struct ClientRef<'a> { impl<'a> core::ops::Deref for ClientRef<'a> { type Target = ClientStore; - fn deref(&self) -> &ClientStore { self.store } + fn deref(&self) -> &ClientStore { + self.store + } } /// An exclusive reference to a [`ClientStore`] together with its index. @@ -228,14 +230,17 @@ pub struct ClientMut<'a> { impl<'a> core::ops::Deref for ClientMut<'a> { type Target = ClientStore; - fn deref(&self) -> &ClientStore { self.store } + fn deref(&self) -> &ClientStore { + self.store + } } impl<'a> core::ops::DerefMut for ClientMut<'a> { - fn deref_mut(&mut self) -> &mut ClientStore { self.store } + fn deref_mut(&mut self) -> &mut ClientStore { + self.store + } } - #[derive(Clone, Debug, borsh::BorshSerialize, borsh::BorshDeserialize)] /// Information about a specific `(port, channel)`. pub struct PortChannelStore { @@ -321,7 +326,6 @@ pub struct Asset { pub effective_decimals_on_sol: u8, } - impl PrivateStorage { /// Returns number of known clients; or counter for the next client. pub fn client_counter(&self) -> u64 { @@ -576,15 +580,21 @@ pub(crate) use from_ctx; pub struct Serialised(Vec, core::marker::PhantomData); impl Serialised { - pub fn empty() -> Self { Self(Vec::new(), core::marker::PhantomData) } + pub fn empty() -> Self { + Self(Vec::new(), core::marker::PhantomData) + } - pub fn is_empty(&self) -> bool { self.0.is_empty() } + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } pub fn transmute(self) -> Serialised { Serialised(self.0, core::marker::PhantomData) } - pub fn as_bytes(&self) -> &[u8] { self.0.as_slice() } + pub fn as_bytes(&self) -> &[u8] { + self.0.as_slice() + } } impl Serialised { diff --git a/solana/solana-ibc/programs/solana-ibc/src/storage/map.rs b/solana/solana-ibc/programs/solana-ibc/src/storage/map.rs index 4f7761b5..f969618e 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/storage/map.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/storage/map.rs @@ -11,7 +11,9 @@ use anchor_lang::prelude::borsh::maybestd::io; pub struct Map(linear_map::LinearMap); impl Default for Map { - fn default() -> Self { Self(Default::default()) } + fn default() -> Self { + Self(Default::default()) + } } impl fmt::Debug for Map { @@ -21,11 +23,15 @@ impl fmt::Debug for Map { } impl From> for Map { - fn from(entries: Vec<(K, V)>) -> Self { Self(entries.into()) } + fn from(entries: Vec<(K, V)>) -> Self { + Self(entries.into()) + } } impl From> for Vec<(K, V)> { - fn from(map: Map) -> Self { Self::from(map.0) } + fn from(map: Map) -> Self { + Self::from(map.0) + } } impl borsh::BorshSerialize for Map diff --git a/solana/solana-ibc/programs/solana-ibc/src/tests.rs b/solana/solana-ibc/programs/solana-ibc/src/tests.rs index 77abd998..62abea6e 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/tests.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/tests.rs @@ -555,9 +555,9 @@ fn anchor_test_deliver() -> Result<()> { sol_rpc_client.get_balance(&fee_collector_pda).unwrap(); assert_eq!( - ((account_balance_before.ui_amount.unwrap() - - account_balance_after.ui_amount.unwrap()) * - 1_000_000_000f64) + ((account_balance_before.ui_amount.unwrap() + - account_balance_after.ui_amount.unwrap()) + * 1_000_000_000f64) .round() as u64, TRANSFER_AMOUNT ); @@ -632,11 +632,11 @@ fn anchor_test_deliver() -> Result<()> { .get_token_account_balance(&receiver_token_address) .unwrap(); assert_eq!( - ((account_balance_after.ui_amount.unwrap() - account_balance_before) * - 10_f64.powf(mint_info.decimals.into())) + ((account_balance_after.ui_amount.unwrap() - account_balance_before) + * 10_f64.powf(mint_info.decimals.into())) .round() as u64, - TRANSFER_AMOUNT / - (10_u64.pow((ORIGINAL_DECIMALS - EFFECTIVE_DECIMALS).into())) + TRANSFER_AMOUNT + / (10_u64.pow((ORIGINAL_DECIMALS - EFFECTIVE_DECIMALS).into())) ); /* @@ -708,12 +708,12 @@ fn anchor_test_deliver() -> Result<()> { sol_rpc_client.get_balance(&fee_collector_pda).unwrap(); assert_eq!( - ((account_balance_before.ui_amount.unwrap() - - account_balance_after.ui_amount.unwrap()) * - 10_f64.powf(mint_info.decimals.into())) + ((account_balance_before.ui_amount.unwrap() + - account_balance_after.ui_amount.unwrap()) + * 10_f64.powf(mint_info.decimals.into())) .round() as u64, - TRANSFER_AMOUNT / - (10_u64.pow((ORIGINAL_DECIMALS - EFFECTIVE_DECIMALS).into())) + TRANSFER_AMOUNT + / (10_u64.pow((ORIGINAL_DECIMALS - EFFECTIVE_DECIMALS).into())) ); assert_eq!(fee_account_balance_after - fee_account_balance_before, FEE); diff --git a/solana/solana-ibc/programs/solana-ibc/src/transfer/impls.rs b/solana/solana-ibc/programs/solana-ibc/src/transfer/impls.rs index 341843ac..2e2e92ec 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/transfer/impls.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/transfer/impls.rs @@ -306,9 +306,9 @@ impl TokenTransferValidationContext for IbcStorage<'_, '_> { let store = self.borrow(); let accounts = &store.accounts; - if accounts.token_program.is_none() || - accounts.token_mint.is_none() || - accounts.mint_authority.is_none() + if accounts.token_program.is_none() + || accounts.token_mint.is_none() + || accounts.mint_authority.is_none() { return Err(TokenTransferError::ParseAccountFailure); } @@ -369,9 +369,9 @@ impl TokenTransferValidationContext for IbcStorage<'_, '_> { let token_mint = get_token_mint(&coin.denom)?; let store = self.borrow(); let accounts = &store.accounts; - if accounts.token_program.is_none() || - accounts.token_mint.is_none() || - accounts.mint_authority.is_none() + if accounts.token_program.is_none() + || accounts.token_mint.is_none() + || accounts.mint_authority.is_none() { return Err(TokenTransferError::ParseAccountFailure); } @@ -534,8 +534,8 @@ impl IbcStorage<'_, '_> { // Close the wsol account so that the receiver gets the amount in native SOL // instead of wrapped SOL which is unusable if the wallet doesnt have any // SOL to pay for the fees. - if matches!(op, EscrowOp::Unescrow) && - coin.denom.base_denom.as_str() == crate::WSOL_ADDRESS + if matches!(op, EscrowOp::Unescrow) + && coin.denom.base_denom.as_str() == crate::WSOL_ADDRESS { let receiver = accounts .receiver @@ -566,8 +566,8 @@ impl IbcStorage<'_, '_> { // Closing the wsol account after transferring the amount to the escrow // so that the escrow account holds the wsol deposits in native SOL which // can be transferred to the receiver instead of sending wrapped sol. - if matches!(op, EscrowOp::Escrow) && - coin.denom.base_denom.as_str() == crate::WSOL_ADDRESS + if matches!(op, EscrowOp::Escrow) + && coin.denom.base_denom.as_str() == crate::WSOL_ADDRESS { let mint_authority = accounts .mint_authority diff --git a/solana/solana-ibc/programs/solana-ibc/src/validation_context.rs b/solana/solana-ibc/programs/solana-ibc/src/validation_context.rs index 7c0624d4..cc452575 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/validation_context.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/validation_context.rs @@ -9,7 +9,6 @@ use crate::consensus_state::AnyConsensusState; use crate::ibc::{self, ConsensusState}; use crate::storage::{self, IbcStorage}; - type Result = core::result::Result; impl ibc::ValidationContext for IbcStorage<'_, '_> { @@ -251,7 +250,9 @@ impl ibc::ValidationContext for IbcStorage<'_, '_> { } } - fn get_client_validation_context(&self) -> &Self::V { self } + fn get_client_validation_context(&self) -> &Self::V { + self + } fn get_compatible_versions(&self) -> Vec { ibc::conn::get_compatible_versions() @@ -296,7 +297,6 @@ impl IbcStorage<'_, '_> { } } - impl ibc::ClientValidationContext for IbcStorage<'_, '_> { fn update_meta( &self, @@ -365,7 +365,7 @@ fn calculate_block_delay( if max_expected_time_per_block.is_zero() { return 0; } - let delay = delay_period_time.as_secs_f64() / - max_expected_time_per_block.as_secs_f64(); + let delay = delay_period_time.as_secs_f64() + / max_expected_time_per_block.as_secs_f64(); delay.ceil() as u64 } diff --git a/solana/trie-example/src/lib.rs b/solana/trie-example/src/lib.rs index 92c85b9f..912b09d4 100644 --- a/solana/trie-example/src/lib.rs +++ b/solana/trie-example/src/lib.rs @@ -65,7 +65,6 @@ impl TrieResultExt for Result { } } - /// Instruction to execute. pub(crate) enum Instruction<'a> { // Encoding: diff --git a/solana/trie/src/account.rs b/solana/trie/src/account.rs index 2dc06106..f59b98ed 100644 --- a/solana/trie/src/account.rs +++ b/solana/trie/src/account.rs @@ -48,10 +48,14 @@ impl<'a, 'info> ResizableAccount<'a, 'info> { impl<'a, 'info> crate::data_ref::DataRef for ResizableAccount<'a, 'info> { #[inline] - fn len(&self) -> usize { self.get(..).map_or(0, |bytes| bytes.len()) } + fn len(&self) -> usize { + self.get(..).map_or(0, |bytes| bytes.len()) + } #[inline] - fn is_empty(&self) -> bool { self.len() == 0 } + fn is_empty(&self) -> bool { + self.len() == 0 + } fn get>(&self, index: I) -> Option<&I::Output> { unsafe fn transmute_lifetime<'a, T: ?Sized>(arg: &T) -> &'a T { diff --git a/solana/trie/src/alloc.rs b/solana/trie/src/alloc.rs index b57927e4..08f35399 100644 --- a/solana/trie/src/alloc.rs +++ b/solana/trie/src/alloc.rs @@ -62,7 +62,6 @@ impl Allocator { } } - /// Address within the trie data. /// /// The value is never zero and when converting from [`Ptr`] always aligned to @@ -71,7 +70,9 @@ impl Allocator { pub(crate) struct Addr(NonZeroU32); impl Addr { - fn new(addr: u32) -> Option { NonZeroU32::new(addr).map(Self) } + fn new(addr: u32) -> Option { + NonZeroU32::new(addr).map(Self) + } /// Returns next properly aligned block or `None` if next address would /// overflow. @@ -81,10 +82,14 @@ impl Addr { /// Cast address to `usize` or retuns `None` if the value doesn’t fit. The /// latter only happens on 16-bit systems. - pub fn usize(self) -> Option { usize::try_from(self.0.get()).ok() } + pub fn usize(self) -> Option { + usize::try_from(self.0.get()).ok() + } /// Returns wrapped `u32` value. - pub fn u32(self) -> u32 { self.0.get() } + pub fn u32(self) -> u32 { + self.0.get() + } /// Returns range of addresses covered by block this address points at. fn range(self) -> core::ops::Range { diff --git a/solana/trie/src/data_ref.rs b/solana/trie/src/data_ref.rs index a1ff3aee..ad73cd08 100644 --- a/solana/trie/src/data_ref.rs +++ b/solana/trie/src/data_ref.rs @@ -4,7 +4,9 @@ pub trait DataRef { fn len(&self) -> usize; /// Returns whether the data is empty. - fn is_empty(&self) -> bool { self.len() == 0 } + fn is_empty(&self) -> bool { + self.len() == 0 + } /// Returns a shared reference to a byte or subslice depending on the type /// of index. @@ -31,7 +33,9 @@ pub trait DataRef { impl DataRef for [u8] { #[inline] - fn len(&self) -> usize { (*self).len() } + fn len(&self) -> usize { + (*self).len() + } fn get>( &self, @@ -48,12 +52,16 @@ impl DataRef for [u8] { } #[inline] - fn enlarge(&mut self, _min_size: usize) -> bool { false } + fn enlarge(&mut self, _min_size: usize) -> bool { + false + } } impl DataRef for [u8; N] { #[inline] - fn len(&self) -> usize { N } + fn len(&self) -> usize { + N + } fn get>( &self, @@ -70,12 +78,16 @@ impl DataRef for [u8; N] { } #[inline] - fn enlarge(&mut self, _min_size: usize) -> bool { false } + fn enlarge(&mut self, _min_size: usize) -> bool { + false + } } impl DataRef for Vec { #[inline] - fn len(&self) -> usize { (**self).len() } + fn len(&self) -> usize { + (**self).len() + } fn get>( &self, @@ -106,7 +118,9 @@ impl DataRef for Vec { } impl DataRef for &'_ mut D { - fn len(&self) -> usize { (**self).len() } + fn len(&self) -> usize { + (**self).len() + } fn get>( &self, @@ -130,7 +144,9 @@ impl DataRef for &'_ mut D { impl DataRef for core::cell::RefMut<'_, D> { #[inline] - fn len(&self) -> usize { (**self).len() } + fn len(&self) -> usize { + (**self).len() + } fn get>( &self, @@ -147,5 +163,7 @@ impl DataRef for core::cell::RefMut<'_, D> { } #[inline] - fn enlarge(&mut self, _min_size: usize) -> bool { false } + fn enlarge(&mut self, _min_size: usize) -> bool { + false + } } diff --git a/solana/trie/src/header.rs b/solana/trie/src/header.rs index 323ed967..1efe19da 100644 --- a/solana/trie/src/header.rs +++ b/solana/trie/src/header.rs @@ -81,7 +81,6 @@ impl Header { } } - #[test] fn test_header_encoding() { const ONE: CryptoHash = CryptoHash([1; 32]); diff --git a/solana/trie/src/lib.rs b/solana/trie/src/lib.rs index ae06d695..6772f04a 100644 --- a/solana/trie/src/lib.rs +++ b/solana/trie/src/lib.rs @@ -15,7 +15,6 @@ pub use account::ResizableAccount; pub use data_ref::DataRef; pub use sealable_trie::Trie; - /// Trie stored in a Solana account. #[derive(Debug)] pub struct TrieAccount( @@ -79,8 +78,8 @@ fn check_account( account: &AccountInfo, owner: &Pubkey, ) -> Result<(), ProgramError> { - if !solana_program::system_program::check_id(account.owner) && - account.lamports() == 0 + if !solana_program::system_program::check_id(account.owner) + && account.lamports() == 0 { Err(ProgramError::UninitializedAccount) } else if account.owner != owner { @@ -110,14 +109,17 @@ impl core::ops::Drop for TrieAccount { impl core::ops::Deref for TrieAccount { type Target = sealable_trie::Trie>; - fn deref(&self) -> &Self::Target { &self.0 } + fn deref(&self) -> &Self::Target { + &self.0 + } } impl core::ops::DerefMut for TrieAccount { - fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } } - #[test] fn test_trie_sanity() { const ONE: lib::hash::CryptoHash = lib::hash::CryptoHash([1; 32]); diff --git a/solana/write-account/src/program.rs b/solana/write-account/src/program.rs index becf0b76..b97021d3 100644 --- a/solana/write-account/src/program.rs +++ b/solana/write-account/src/program.rs @@ -66,7 +66,6 @@ fn process_instruction<'a>( } } - /// Handles the Write operation. fn handle_write( program_id: &Pubkey, @@ -151,7 +150,6 @@ fn setup_write_account( } } - /// Handles Free operation. fn handle_free(accounts: Accounts) -> Result { { @@ -168,7 +166,6 @@ fn handle_free(accounts: Accounts) -> Result { accounts.write.realloc(0, false) } - /// Accounts used when processing instruction. #[derive(Clone, Copy)] struct Accounts<'a, 'info> { @@ -238,7 +235,6 @@ impl<'a, 'info> Accounts<'a, 'info> { } } - /// Reads given object from the start of the slice advancing it. /// /// Returns an error if slice is too short. diff --git a/validator/src/main.rs b/validator/src/main.rs index a5bb21c4..f1e04daf 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -3,4 +3,6 @@ mod stake; mod utils; mod validator; -fn main() { command::process_command(); } +fn main() { + command::process_command(); +} From 4cd90032d35b1231db95442a2284ba4d47401612 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Tue, 20 Aug 2024 15:23:21 +0530 Subject: [PATCH 15/47] add single domain in intent --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 6 ++++-- solana/bridge-escrow/programs/bridge-escrow/src/tests.rs | 3 +-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 89e1dcb3..965c2c0e 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -72,6 +72,7 @@ pub mod bridge_escrow { amount_out: String, timeout_in_sec: u64, winner_solver: Pubkey, + single_domain: bool, ) -> Result<()> { // verify if caller is auctioneer let auctioneer = &ctx.accounts.auctioneer; @@ -90,6 +91,7 @@ pub mod bridge_escrow { intent.timeout_timestamp_in_sec = timeout_in_sec; intent.amount_out = amount_out; intent.winner_solver = winner_solver; + intent.single_domain = single_domain; Ok(()) } @@ -141,7 +143,6 @@ pub mod bridge_escrow { ctx: Context, hashed_full_denom: Option, solver_out: Option, - single_domain: bool, ) -> Result<()> { let intent = &ctx.accounts.intent; require!( @@ -173,7 +174,7 @@ pub mod bridge_escrow { amount_out, )?; - if single_domain { + if intent.single_domain { // Transfer tokens from Auctioneer to Solver let bump = ctx.bumps.auctioneer_state; @@ -392,6 +393,7 @@ pub struct Intent { // Timestamp when the intent was created pub creation_timestamp_in_sec: u64, pub timeout_timestamp_in_sec: u64, + pub single_domain: bool } // Define the context for initializing the program diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index 7bea10b8..b55f3fb2 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -283,6 +283,7 @@ fn escrow_bridge_program() -> Result<()> { amount_out: amount_out.to_string(), timeout_in_sec: 10000, winner_solver: solver.pubkey(), + single_domain: true, }) .payer(auctioneer.clone()) .signer(&*auctioneer) @@ -334,10 +335,8 @@ fn escrow_bridge_program() -> Result<()> { fee_collector: None, }) .args(crate::instruction::SendFundsToUser { - intent_id, hashed_full_denom: None, solver_out: None, - single_domain: true, }) .payer(solver.clone()) .signer(&*solver) From 01ae66cd1bfda96e4e192ce92deea8e2cc6128b3 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Tue, 20 Aug 2024 19:29:24 +0530 Subject: [PATCH 16/47] update tests and send funds to user method --- .../programs/bridge-escrow/src/lib.rs | 1 + .../programs/bridge-escrow/src/tests.rs | 39 ++++++++++++++++--- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 965c2c0e..aa9174ca 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -141,6 +141,7 @@ pub mod bridge_escrow { // this function is called by Solver pub fn send_funds_to_user( ctx: Context, + intent_id: String, hashed_full_denom: Option, solver_out: Option, ) -> Result<()> { diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index b55f3fb2..df2e3c19 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -9,14 +9,17 @@ use anchor_client::solana_sdk::commitment_config::CommitmentConfig; use anchor_client::solana_sdk::compute_budget::ComputeBudgetInstruction; use anchor_client::solana_sdk::pubkey::Pubkey; use anchor_client::solana_sdk::signature::{ - Keypair, Signature, Signer as SolanaSigner, + read_keypair_file, Keypair, Signature, Signer as SolanaSigner, }; +use anchor_client::solana_sdk::system_transaction::transfer; use anchor_client::{Client, Cluster}; use anchor_lang::system_program; use anchor_spl::associated_token::{self, get_associated_token_address}; use anyhow::Result; use ibc::apps::transfer::types::{PrefixedCoin, PrefixedDenom}; +use lib::hash::CryptoHash; use spl_token::instruction::initialize_mint2; +use spl_token::solana_program::native_token::LAMPORTS_PER_SOL; use spl_token::solana_program::system_instruction::create_account; const MINT_AMOUNT: u64 = 1_000_000_000; @@ -39,11 +42,11 @@ fn airdrop(client: &RpcClient, account: Pubkey, lamports: u64) -> Signature { #[ignore = "Requires local validator to run"] fn escrow_bridge_program() -> Result<()> { // Setup the client and wallet - let user = Rc::new(Keypair::new()); + let auctioneer = Rc::new(read_keypair_file("../../../solana-ibc/keypair.json").unwrap()); let client = Client::new_with_options( Cluster::Localnet, - user.clone(), + auctioneer.clone(), CommitmentConfig::processed(), ); @@ -53,7 +56,7 @@ fn escrow_bridge_program() -> Result<()> { let lamports = 2_000_000_000; let solver = Rc::new(Keypair::new()); - let auctioneer = Rc::new(Keypair::new()); + let user = Rc::new(Keypair::new()); let token_in_keypair = Keypair::new(); let token_in = token_in_keypair.pubkey(); let token_out_keypair = Keypair::new(); @@ -61,6 +64,29 @@ fn escrow_bridge_program() -> Result<()> { let program_rpc = program.rpc(); + // Below is for Devnet/Mainnet + + // println!("User {:?}", user.to_bytes()); + // println!("Solver {:?}", solver.to_bytes()); + + // let blockhash = program_rpc.get_latest_blockhash()?; + // let user_transfer_ix = + // transfer(&auctioneer, &user.pubkey(), LAMPORTS_PER_SOL / 10, blockhash); + // let solver_transfer_ix = transfer( + // &auctioneer, + // &solver.pubkey(), + // LAMPORTS_PER_SOL / 10, + // blockhash, + // ); + + // let user_transfer_sig = + // program_rpc.send_and_confirm_transaction(&user_transfer_ix)?; + // let solver_transfer_sig = + // program_rpc.send_and_confirm_transaction(&solver_transfer_ix)?; + + // println!("User transfer signature: {}", user_transfer_sig); + // println!("Solver transfer signature: {}", solver_transfer_sig); + airdrop(&program_rpc, auctioneer.pubkey(), lamports); airdrop(&program_rpc, user.pubkey(), lamports); airdrop(&program_rpc, solver.pubkey(), lamports); @@ -255,7 +281,8 @@ fn escrow_bridge_program() -> Result<()> { // ); // Store the intent - let intent_id = "123234".to_string(); + println!("Store the intent"); + let intent_id = "12323542".to_string(); // arbitrary value let amount_out = 10000; @@ -295,6 +322,7 @@ fn escrow_bridge_program() -> Result<()> { println!(" Signature: {}", sig); // Send funds to user ( single domain ) + println!("Send funds to user single domain"); let solver_token_in_addr = get_associated_token_address(&solver.pubkey(), &token_in); @@ -335,6 +363,7 @@ fn escrow_bridge_program() -> Result<()> { fee_collector: None, }) .args(crate::instruction::SendFundsToUser { + intent_id: intent_id.clone(), hashed_full_denom: None, solver_out: None, }) From 0e41399021ae3c118a2874be9e05570dd2c2ecd0 Mon Sep 17 00:00:00 2001 From: doradelta <64730977+doradelta@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:26:41 +0200 Subject: [PATCH 17/47] Update lib.rs --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index aa9174ca..9fb46d62 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -29,7 +29,7 @@ const INTENT_SEED: &[u8] = b"intent"; #[cfg(test)] mod tests; -declare_id!("EcKk7ZzNPHBougPDZ2Rwu93xd48ba1X6cwW1j8DUChHP"); +declare_id!("7XYDdCQWB86QXBThmzENF19wnv2bgBvTJMsKzEZ3k8kE"); #[program] pub mod bridge_escrow { From aec6bf805f75fcd5fbe1f045312f3ffd1359fef5 Mon Sep 17 00:00:00 2001 From: doradelta <64730977+doradelta@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:33:45 +0200 Subject: [PATCH 18/47] Update lib.rs --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 9fb46d62..da4b1069 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -29,7 +29,7 @@ const INTENT_SEED: &[u8] = b"intent"; #[cfg(test)] mod tests; -declare_id!("7XYDdCQWB86QXBThmzENF19wnv2bgBvTJMsKzEZ3k8kE"); +declare_id!("3N4WXdP7FZQ1u9sjhKp5Gth6Tg8YkM3vV7q2SjQf5LZG"); #[program] pub mod bridge_escrow { From 93d26adcbe3c2fbb95d1411359ba07e80e8632cc Mon Sep 17 00:00:00 2001 From: banegil Date: Tue, 20 Aug 2024 16:38:34 +0200 Subject: [PATCH 19/47] update escrow id --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index da4b1069..2caf978c 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -29,7 +29,7 @@ const INTENT_SEED: &[u8] = b"intent"; #[cfg(test)] mod tests; -declare_id!("3N4WXdP7FZQ1u9sjhKp5Gth6Tg8YkM3vV7q2SjQf5LZG"); +declare_id!("64K4AFty7UK9VJC6qykEVwFA93VoyND2uGyQgYa98ui9"); #[program] pub mod bridge_escrow { From f821b3509e304ffc46bcc2368f88edfd42305af4 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Thu, 22 Aug 2024 12:20:30 +0530 Subject: [PATCH 20/47] fmt --- common/cf-guest/src/client.rs | 8 +-- common/cf-guest/src/client/impls.rs | 8 +-- common/cf-guest/src/header.rs | 4 +- common/cf-guest/src/message.rs | 32 +++------- common/cf-guest/src/misbehaviour.rs | 4 +- common/cf-guest/src/proof.rs | 18 ++---- common/guestchain/src/block.rs | 12 ++-- common/guestchain/src/candidates.rs | 12 +--- common/guestchain/src/candidates/tests.rs | 24 ++++---- common/guestchain/src/epoch.rs | 4 +- common/guestchain/src/height.rs | 24 ++------ common/guestchain/src/manager.rs | 22 +++---- common/guestchain/src/validators.rs | 24 ++------ common/lib/src/hash.rs | 44 ++++---------- common/lib/src/u3.rs | 24 ++------ common/memory/src/lib.rs | 12 +--- common/proto-utils/src/lib.rs | 4 +- common/proto-utils/src/tests.rs | 8 +-- common/sealable-trie/src/bits.rs | 52 +++++----------- common/sealable-trie/src/bits/concat.rs | 8 +-- common/sealable-trie/src/bits/ext_key.rs | 12 +--- common/sealable-trie/src/nodes.rs | 8 +-- common/sealable-trie/src/proof.rs | 28 +++------ .../sealable-trie/src/proof/serialisation.rs | 14 ++--- common/sealable-trie/src/trie.rs | 16 ++--- common/sealable-trie/src/trie/del.rs | 4 +- common/sealable-trie/src/trie/tests.rs | 60 +++++-------------- common/trie-ids/src/ids.rs | 52 ++++------------ common/trie-ids/src/path_info.rs | 4 +- common/trie-ids/src/trie_key.rs | 20 ++----- common/wasm/src/consensus_state.rs | 4 +- solana/allocator/src/lib.rs | 4 +- .../programs/bridge-escrow/src/lib.rs | 2 +- .../programs/bridge-escrow/src/tests.rs | 15 ++--- .../restaking/programs/restaking/src/lib.rs | 8 +-- .../restaking/programs/restaking/src/token.rs | 38 +++++------- solana/signature-verifier/src/api.rs | 4 +- solana/signature-verifier/src/ed25519.rs | 16 ++--- .../signature-verifier/src/ed25519_program.rs | 30 +++------- solana/signature-verifier/src/verifier.rs | 8 +-- .../programs/solana-ibc/src/allocator.rs | 4 +- .../programs/solana-ibc/src/chain.rs | 12 +--- .../solana-ibc/src/client_state/impls.rs | 24 ++------ .../programs/solana-ibc/src/error.rs | 20 ++----- .../solana-ibc/src/execution_context.rs | 12 +--- .../solana-ibc/src/ix_data_account.rs | 16 ++--- .../solana-ibc/programs/solana-ibc/src/lib.rs | 19 +++--- .../programs/solana-ibc/src/storage.rs | 24 ++------ .../programs/solana-ibc/src/storage/map.rs | 12 +--- .../programs/solana-ibc/src/tests.rs | 24 ++++---- .../programs/solana-ibc/src/transfer/impls.rs | 20 +++---- .../solana-ibc/src/validation_context.rs | 8 +-- solana/trie/src/account.rs | 8 +-- solana/trie/src/alloc.rs | 12 +--- solana/trie/src/data_ref.rs | 36 +++-------- solana/trie/src/lib.rs | 12 ++-- validator/src/main.rs | 4 +- 57 files changed, 288 insertions(+), 674 deletions(-) diff --git a/common/cf-guest/src/client.rs b/common/cf-guest/src/client.rs index 1fffb0e9..3502bc60 100644 --- a/common/cf-guest/src/client.rs +++ b/common/cf-guest/src/client.rs @@ -96,15 +96,11 @@ impl ClientState { this } - pub fn frozen(&self) -> Self { - Self { is_frozen: true, ..self.clone() } - } + pub fn frozen(&self) -> Self { Self { is_frozen: true, ..self.clone() } } } impl From> for proto::ClientState { - fn from(state: ClientState) -> Self { - Self::from(&state) - } + fn from(state: ClientState) -> Self { Self::from(&state) } } impl From<&ClientState> for proto::ClientState { diff --git a/common/cf-guest/src/client/impls.rs b/common/cf-guest/src/client/impls.rs index e83baca4..84c19c30 100644 --- a/common/cf-guest/src/client/impls.rs +++ b/common/cf-guest/src/client/impls.rs @@ -43,9 +43,7 @@ pub enum Neighbourhood { } impl Default for Neighbourhood { - fn default() -> Self { - Self::Neighbours(None, None) - } + fn default() -> Self { Self::Neighbours(None, None) } } impl Neighbourhood { @@ -480,8 +478,8 @@ impl ClientState { if header.genesis_hash != self.genesis_hash { return Err("Unexpected genesis hash"); } - if header.epoch_commitment != self.epoch_commitment - && header.epoch_commitment != self.prev_epoch_commitment + if header.epoch_commitment != self.epoch_commitment && + header.epoch_commitment != self.prev_epoch_commitment { return Err("Unexpected epoch"); } diff --git a/common/cf-guest/src/header.rs b/common/cf-guest/src/header.rs index 25855d99..7d440726 100644 --- a/common/cf-guest/src/header.rs +++ b/common/cf-guest/src/header.rs @@ -71,9 +71,7 @@ impl Header { } impl From> for proto::Header { - fn from(header: Header) -> Self { - Self::from(&header) - } + fn from(header: Header) -> Self { Self::from(&header) } } impl From<&Header> for proto::Header { diff --git a/common/cf-guest/src/message.rs b/common/cf-guest/src/message.rs index 0503b786..9c94d2bb 100644 --- a/common/cf-guest/src/message.rs +++ b/common/cf-guest/src/message.rs @@ -18,9 +18,7 @@ pub enum ClientMessage { // Conversions directly to and from the Message enum. impl From> for Message { - fn from(msg: ClientMessage) -> Self { - Self::from(&msg) - } + fn from(msg: ClientMessage) -> Self { Self::from(&msg) } } impl From<&ClientMessage> for Message { @@ -52,41 +50,29 @@ impl TryFrom<&Message> for ClientMessage { // Conversions directly into the Message enum from variant types. impl From> for Message { - fn from(msg: Header) -> Self { - Self::Header(msg.into()) - } + fn from(msg: Header) -> Self { Self::Header(msg.into()) } } impl From<&Header> for Message { - fn from(msg: &Header) -> Self { - Self::Header(msg.into()) - } + fn from(msg: &Header) -> Self { Self::Header(msg.into()) } } impl From> for Message { - fn from(msg: Misbehaviour) -> Self { - Self::Misbehaviour(msg.into()) - } + fn from(msg: Misbehaviour) -> Self { Self::Misbehaviour(msg.into()) } } impl From<&Misbehaviour> for Message { - fn from(msg: &Misbehaviour) -> Self { - Self::Misbehaviour(msg.into()) - } + fn from(msg: &Misbehaviour) -> Self { Self::Misbehaviour(msg.into()) } } // Conversion into ClientMessage proto from variant types. impl From> for proto::ClientMessage { - fn from(msg: Header) -> Self { - Self { message: Some(msg.into()) } - } + fn from(msg: Header) -> Self { Self { message: Some(msg.into()) } } } impl From<&Header> for proto::ClientMessage { - fn from(msg: &Header) -> Self { - Self { message: Some(msg.into()) } - } + fn from(msg: &Header) -> Self { Self { message: Some(msg.into()) } } } impl From> for proto::ClientMessage { @@ -104,9 +90,7 @@ impl From<&Misbehaviour> for proto::ClientMessage { // And finally, conversions between proto and Rust type impl From> for proto::ClientMessage { - fn from(msg: ClientMessage) -> Self { - Self::from(&msg) - } + fn from(msg: ClientMessage) -> Self { Self::from(&msg) } } impl From<&ClientMessage> for proto::ClientMessage { diff --git a/common/cf-guest/src/misbehaviour.rs b/common/cf-guest/src/misbehaviour.rs index 73da6a84..73e7fe32 100644 --- a/common/cf-guest/src/misbehaviour.rs +++ b/common/cf-guest/src/misbehaviour.rs @@ -9,9 +9,7 @@ pub struct Misbehaviour { } impl From> for proto::Misbehaviour { - fn from(msg: Misbehaviour) -> Self { - Self::from(&msg) - } + fn from(msg: Misbehaviour) -> Self { Self::from(&msg) } } impl From<&Misbehaviour> for proto::Misbehaviour { diff --git a/common/cf-guest/src/proof.rs b/common/cf-guest/src/proof.rs index 8257dadd..7f82c2bf 100644 --- a/common/cf-guest/src/proof.rs +++ b/common/cf-guest/src/proof.rs @@ -23,14 +23,10 @@ pub struct IbcProof { impl IbcProof { /// Returns commitment prefix to use during verification. - pub fn prefix(&self) -> ibc::CommitmentPrefix { - Default::default() - } + pub fn prefix(&self) -> ibc::CommitmentPrefix { Default::default() } /// Returns commitment root. - pub fn root(&self) -> ibc::CommitmentRoot { - self.root.to_vec().into() - } + pub fn root(&self) -> ibc::CommitmentRoot { self.root.to_vec().into() } /// Consumes object and returns commitment proof. pub fn proof(self) -> ibc::CommitmentProofBytes { @@ -188,9 +184,9 @@ pub fn verify( <&CryptoHash>::try_from(root).map_err(|_| VerifyError::BadRoot)?; let is_packet_commitment = matches!( path, - ibc::path::Path::Commitment(_) - | ibc::path::Path::Receipt(_) - | ibc::path::Path::Ack(_) + ibc::path::Path::Commitment(_) | + ibc::path::Path::Receipt(_) | + ibc::path::Path::Ack(_) ); let path = trie_ids::PathInfo::try_from(path)?; @@ -274,9 +270,7 @@ fn test_proofs() { self.header.state_root = self.trie.hash().clone(); } - fn root(&self) -> &CryptoHash { - self.trie.hash() - } + fn root(&self) -> &CryptoHash { self.trie.hash() } } /// Takes a proof and substitutes the block header encoded in it. diff --git a/common/guestchain/src/block.rs b/common/guestchain/src/block.rs index 58935c4c..478ee294 100644 --- a/common/guestchain/src/block.rs +++ b/common/guestchain/src/block.rs @@ -187,8 +187,8 @@ impl BlockHeader { /// Returns whether the block is a valid genesis block. pub fn is_genesis(&self) -> bool { - self.prev_block_hash == CryptoHash::DEFAULT - && self.epoch_id == CryptoHash::DEFAULT + self.prev_block_hash == CryptoHash::DEFAULT && + self.epoch_id == CryptoHash::DEFAULT } /// Calculates hash of the block. @@ -268,9 +268,7 @@ impl Block { } impl Default for Fingerprint { - fn default() -> Self { - Self([0; 72]) - } + fn default() -> Self { Self([0; 72]) } } impl Fingerprint { @@ -306,9 +304,7 @@ impl Fingerprint { /// Returns the fingerprint as bytes slice. #[inline] - pub fn as_slice(&self) -> &[u8] { - &self.0[..] - } + pub fn as_slice(&self) -> &[u8] { &self.0[..] } /// Signs the fingerprint #[inline] diff --git a/common/guestchain/src/candidates.rs b/common/guestchain/src/candidates.rs index 4e72177c..8319308d 100644 --- a/common/guestchain/src/candidates.rs +++ b/common/guestchain/src/candidates.rs @@ -93,9 +93,7 @@ impl Candidates { } /// Returns stake held by first `max_validators` candidates. - pub fn current_head_stake(&self) -> u128 { - self.head_stake - } + pub fn current_head_stake(&self) -> u128 { self.head_stake } /// Sums stake of the first `count` candidates. fn sum_head_stake(count: NonZeroU16, candidates: &[Candidate]) -> u128 { @@ -137,9 +135,7 @@ impl Candidates { /// Changed flag is set automatically whenever head of the candidates list /// is modified (note that changes outside of the head of candidates list do /// not affect the flag). - pub fn clear_changed_flag(&mut self) { - self.changed = false; - } + pub fn clear_changed_flag(&mut self) { self.changed = false; } /// Adds a new candidates or updates existing candidate’s stake. /// @@ -336,9 +332,7 @@ impl Candidates { impl Candidates { /// Convenience method which returns `self.max_validators` as `usize`. - fn max_validators(&self) -> usize { - usize::from(self.max_validators.get()) - } + fn max_validators(&self) -> usize { usize::from(self.max_validators.get()) } } /// Rotates subslice such that element at `old_pos` moves to `new_pos`. diff --git a/common/guestchain/src/candidates/tests.rs b/common/guestchain/src/candidates/tests.rs index a7adf3db..ce49383c 100644 --- a/common/guestchain/src/candidates/tests.rs +++ b/common/guestchain/src/candidates/tests.rs @@ -127,9 +127,7 @@ fn test_candidates_0() { use candidate as c; use UpdateCandidateError::*; - fn pk(pubkey: char) -> MockPubKey { - MockPubKey(pubkey as u32) - } + fn pk(pubkey: char) -> MockPubKey { MockPubKey(pubkey as u32) } // Create candidates set let mut candidates = Candidates::from_candidates( @@ -305,8 +303,8 @@ impl TestCtx { /// configuration file. fn check(&self) { assert!( - self.candidates.candidates.len() - >= usize::from(self.config.min_validators.get()), + self.candidates.candidates.len() >= + usize::from(self.config.min_validators.get()), "Violated min validators constraint: {} < {}", self.candidates.candidates.len(), self.config.min_validators.get(), @@ -347,14 +345,14 @@ impl TestCtx { .get(usize::from(self.config.max_validators.get())) .map_or(0, |c: &Candidate<_>| c.stake.get()); assert!( - head_stake - old_stake + new_stake - < self.config.min_total_stake.get() + head_stake - old_stake + new_stake < + self.config.min_total_stake.get() ); } NotEnoughValidators => { assert!( - self.candidates.candidates.len() - <= usize::from(self.config.min_validators.get()) + self.candidates.candidates.len() <= + usize::from(self.config.min_validators.get()) ); } } @@ -427,8 +425,8 @@ impl TestCtx { .candidates .get(usize::from(self.config.max_validators.get())); let kicked_out = last.clone().map_or(false, |candidiate| { - candidiate - < &Candidate { + candidiate < + &Candidate { pubkey, stake: NonZeroU128::new(new_stake).unwrap(), } @@ -438,8 +436,8 @@ impl TestCtx { if kicked_out { last.unwrap().stake.get() } else { new_stake }; assert!( - self.candidates.head_stake - old_stake + new_stake - < self.config.min_total_stake.get() + self.candidates.head_stake - old_stake + new_stake < + self.config.min_total_stake.get() ); } diff --git a/common/guestchain/src/epoch.rs b/common/guestchain/src/epoch.rs index 3a33be04..75620e75 100644 --- a/common/guestchain/src/epoch.rs +++ b/common/guestchain/src/epoch.rs @@ -96,9 +96,7 @@ impl Epoch { } /// Returns stake needed to reach quorum. - pub fn quorum_stake(&self) -> NonZeroU128 { - self.quorum_stake - } + pub fn quorum_stake(&self) -> NonZeroU128 { self.quorum_stake } /// Finds a validator by their public key. pub fn validator(&self, pk: &PK) -> Option<&crate::Validator> diff --git a/common/guestchain/src/height.rs b/common/guestchain/src/height.rs index 2513f903..a7d6f253 100644 --- a/common/guestchain/src/height.rs +++ b/common/guestchain/src/height.rs @@ -31,9 +31,7 @@ pub type BlockDelta = Delta; impl Height { /// Returns the next height, i.e. `self + 1`. - pub fn next(self) -> Self { - Self(self.0.checked_add(1).unwrap(), self.1) - } + pub fn next(self) -> Self { Self(self.0.checked_add(1).unwrap(), self.1) } /// Checks whether delta between two heights is at least `min`. /// @@ -53,23 +51,17 @@ impl Height { macro_rules! impls { ($ty:ident) => { impl Clone for $ty { - fn clone(&self) -> Self { - *self - } + fn clone(&self) -> Self { *self } } impl Copy for $ty {} impl From for $ty { - fn from(value: u64) -> Self { - Self(value, Default::default()) - } + fn from(value: u64) -> Self { Self(value, Default::default()) } } impl From<$ty> for u64 { - fn from(value: $ty) -> u64 { - value.0 - } + fn from(value: $ty) -> u64 { value.0 } } impl fmt::Debug for $ty { @@ -85,9 +77,7 @@ macro_rules! impls { } impl PartialEq for $ty { - fn eq(&self, rhs: &Self) -> bool { - self.0 == rhs.0 - } + fn eq(&self, rhs: &Self) -> bool { self.0 == rhs.0 } } impl Eq for $ty {} @@ -99,9 +89,7 @@ macro_rules! impls { } impl Ord for $ty { - fn cmp(&self, rhs: &Self) -> cmp::Ordering { - self.0.cmp(&rhs.0) - } + fn cmp(&self, rhs: &Self) -> cmp::Ordering { self.0.cmp(&rhs.0) } } impl borsh::BorshSerialize for $ty { diff --git a/common/guestchain/src/manager.rs b/common/guestchain/src/manager.rs index ac2ec4d4..282b78a8 100644 --- a/common/guestchain/src/manager.rs +++ b/common/guestchain/src/manager.rs @@ -120,12 +120,8 @@ pub enum AddSignatureEffect { } impl AddSignatureEffect { - pub fn got_new_signature(self) -> bool { - self != Self::Duplicate - } - pub fn got_quorum(self) -> bool { - self == Self::GotQuorum - } + pub fn got_new_signature(self) -> bool { self != Self::Duplicate } + pub fn got_quorum(self) -> bool { self == Self::GotQuorum } } impl ChainManager { @@ -255,9 +251,9 @@ impl ChainManager { let next_epoch = self.maybe_generate_next_epoch(host_height); let age = host_timestamp.get().saturating_sub(self.header.timestamp_ns.get()); - if next_epoch.is_none() - && state_root == &self.header.state_root - && age < self.config.max_block_age_ns + if next_epoch.is_none() && + state_root == &self.header.state_root && + age < self.config.max_block_age_ns { return Err(GenerateError::UnchangedState); }; @@ -360,13 +356,9 @@ impl ChainManager { self.candidates.candidates.as_slice() } - pub fn epoch_height(&self) -> crate::HostHeight { - self.epoch_height - } + pub fn epoch_height(&self) -> crate::HostHeight { self.epoch_height } - pub fn genesis(&self) -> &CryptoHash { - &self.genesis - } + pub fn genesis(&self) -> &CryptoHash { &self.genesis } } #[test] diff --git a/common/guestchain/src/validators.rs b/common/guestchain/src/validators.rs index 8f5d40e9..4b663e81 100644 --- a/common/guestchain/src/validators.rs +++ b/common/guestchain/src/validators.rs @@ -19,9 +19,7 @@ pub trait PubKey: type Signature: Signature; fn as_bytes(&self) -> alloc::borrow::Cow<'_, [u8]>; - fn to_vec(&self) -> Vec { - self.as_bytes().into_owned() - } + fn to_vec(&self) -> Vec { self.as_bytes().into_owned() } fn from_bytes(bytes: &[u8]) -> Result; } @@ -30,9 +28,7 @@ pub trait Signature: Clone + Eq + core::fmt::Debug + borsh::BorshSerialize + borsh::BorshDeserialize { fn as_bytes(&self) -> alloc::borrow::Cow<'_, [u8]>; - fn to_vec(&self) -> Vec { - self.as_bytes().into_owned() - } + fn to_vec(&self) -> Vec { self.as_bytes().into_owned() } fn from_bytes(bytes: &[u8]) -> Result; } @@ -74,19 +70,13 @@ impl Validator { Self { version: crate::common::VersionZero, pubkey, stake } } - pub fn pubkey(&self) -> &PK { - &self.pubkey - } + pub fn pubkey(&self) -> &PK { &self.pubkey } - pub fn stake(&self) -> NonZeroU128 { - self.stake - } + pub fn stake(&self) -> NonZeroU128 { self.stake } } impl From for BadFormat { - fn from(_: core::array::TryFromSliceError) -> BadFormat { - BadFormat - } + fn from(_: core::array::TryFromSliceError) -> BadFormat { BadFormat } } #[cfg(any(test, feature = "test_utils"))] @@ -109,9 +99,7 @@ pub(crate) mod test_utils { pub struct MockPubKey(pub u32); impl MockPubKey { - pub fn make_signer(&self) -> MockSigner { - MockSigner(*self) - } + pub fn make_signer(&self) -> MockSigner { MockSigner(*self) } } /// A mock implementation of a Signer. Offers no security; intended for diff --git a/common/lib/src/hash.rs b/common/lib/src/hash.rs index 15433dc7..cd80999b 100644 --- a/common/lib/src/hash.rs +++ b/common/lib/src/hash.rs @@ -39,9 +39,7 @@ impl CryptoHash { /// Returns a builder which can be used to construct cryptographic hash by /// digesting bytes. #[inline] - pub fn builder() -> Builder { - Builder::default() - } + pub fn builder() -> Builder { Builder::default() } /// Returns hash of given bytes. #[inline] @@ -61,9 +59,7 @@ impl CryptoHash { /// `solana` crate feature must be enabled for this Solana-specific /// optimisation to be implemented. #[inline] - pub fn digestv(slices: &[&[u8]]) -> Self { - Self(imp::digestv(slices)) - } + pub fn digestv(slices: &[&[u8]]) -> Self { Self(imp::digestv(slices)) } /// Decodes a base64 string representation of the hash. pub fn from_base64(base64: &str) -> Option { @@ -96,21 +92,15 @@ impl CryptoHash { /// Returns a shared reference to the underlying bytes array. #[inline] - pub fn as_array(&self) -> &[u8; Self::LENGTH] { - &self.0 - } + pub fn as_array(&self) -> &[u8; Self::LENGTH] { &self.0 } /// Returns a shared reference to the hash as slice of bytes. #[inline] - pub fn as_slice(&self) -> &[u8] { - &self.0[..] - } + pub fn as_slice(&self) -> &[u8] { &self.0[..] } /// Allocates vector with the contents of the hash. #[inline] - pub fn to_vec(&self) -> alloc::vec::Vec { - self.as_slice().to_vec() - } + pub fn to_vec(&self) -> alloc::vec::Vec { self.as_slice().to_vec() } } impl core::fmt::Display for CryptoHash { @@ -142,9 +132,7 @@ impl<'a> From<&'a [u8; CryptoHash::LENGTH]> for CryptoHash { impl From<&'_ CryptoHash> for [u8; CryptoHash::LENGTH] { #[inline] - fn from(hash: &'_ CryptoHash) -> Self { - hash.0 - } + fn from(hash: &'_ CryptoHash) -> Self { hash.0 } } impl<'a> From<&'a [u8; CryptoHash::LENGTH]> for &'a CryptoHash { @@ -205,14 +193,10 @@ mod imp { impl State { #[inline] - pub fn update(&mut self, bytes: &[u8]) { - self.0.update(bytes) - } + pub fn update(&mut self, bytes: &[u8]) { self.0.update(bytes) } #[inline] - pub fn done(self) -> [u8; 32] { - self.0.finalize().into() - } + pub fn done(self) -> [u8; 32] { self.0.finalize().into() } } } @@ -254,15 +238,11 @@ pub struct Builder(imp::State); impl Builder { /// Process data, updating the internal state of the digest. #[inline] - pub fn update(&mut self, bytes: &[u8]) { - self.0.update(bytes) - } + pub fn update(&mut self, bytes: &[u8]) { self.0.update(bytes) } /// Finalises the digest and returns the cryptographic hash. #[inline] - pub fn build(self) -> CryptoHash { - CryptoHash(self.0.done()) - } + pub fn build(self) -> CryptoHash { CryptoHash(self.0.done()) } } #[cfg(feature = "borsh")] @@ -276,9 +256,7 @@ impl io::Write for Builder { Ok(self.update(buf)) } - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } + fn flush(&mut self) -> io::Result<()> { Ok(()) } } #[test] diff --git a/common/lib/src/u3.rs b/common/lib/src/u3.rs index 307abff0..89dc8e90 100644 --- a/common/lib/src/u3.rs +++ b/common/lib/src/u3.rs @@ -36,9 +36,7 @@ impl U3 { /// Divides argument by eight and returns quotient and reminder of the /// operation. - pub fn divmod(value: u16) -> (u16, U3) { - (value / 8, Self::wrap(value)) - } + pub fn divmod(value: u16) -> (u16, U3) { (value / 8, Self::wrap(value)) } /// Returns an iterator over all `U3` values in ascending order. pub fn all() -> impl core::iter::Iterator { @@ -50,18 +48,14 @@ impl U3 { } #[inline] - pub fn wrapping_inc(self) -> U3 { - self.wrapping_add(1u8) - } + pub fn wrapping_inc(self) -> U3 { self.wrapping_add(1u8) } pub fn wrapping_sub(self, rhs: impl Unsigned) -> U3 { U3::wrap(self.into_integer().wrapping_sub(rhs.as_u8())) } #[inline] - pub fn wrapping_dec(self) -> U3 { - self.wrapping_add(7u8) - } + pub fn wrapping_dec(self) -> U3 { self.wrapping_add(7u8) } #[inline] pub fn checked_inc(self) -> Option { @@ -76,22 +70,16 @@ impl U3 { impl Default for U3 { #[inline] - fn default() -> Self { - Self::MIN - } + fn default() -> Self { Self::MIN } } impl Unsigned for U3 { - fn as_u8(self) -> u8 { - self.into_integer() - } + fn as_u8(self) -> u8 { self.into_integer() } } impl ops::Neg for U3 { type Output = U3; - fn neg(self) -> U3 { - U3::_0.wrapping_sub(self) - } + fn neg(self) -> U3 { U3::_0.wrapping_sub(self) } } macro_rules! impls { diff --git a/common/memory/src/lib.rs b/common/memory/src/lib.rs index 813e1dae..f8a7713a 100644 --- a/common/memory/src/lib.rs +++ b/common/memory/src/lib.rs @@ -193,9 +193,7 @@ impl<'a, A: Allocator> WriteLog<'a, A> { } /// Returns underlying allocator. - pub fn allocator(&self) -> &A { - &*self.alloc - } + pub fn allocator(&self) -> &A { &*self.alloc } pub fn alloc(&mut self, value: A::Value) -> Result { Ok(if let Some(ptr) = self.freed.pop() { @@ -212,9 +210,7 @@ impl<'a, A: Allocator> WriteLog<'a, A> { self.write_log.push((ptr, value)) } - pub fn free(&mut self, ptr: Ptr) { - self.freed.push(ptr); - } + pub fn free(&mut self, ptr: Ptr) { self.freed.push(ptr); } } impl<'a, A: Allocator> core::ops::Drop for WriteLog<'a, A> { @@ -245,9 +241,7 @@ pub mod test_utils { Self { count: 0, pool, free_list: Default::default() } } - pub fn count(&self) -> usize { - self.count - } + pub fn count(&self) -> usize { self.count } /// Gets index in the memory pool for the given pointer. /// diff --git a/common/proto-utils/src/lib.rs b/common/proto-utils/src/lib.rs index ede0ac90..c7708995 100644 --- a/common/proto-utils/src/lib.rs +++ b/common/proto-utils/src/lib.rs @@ -63,9 +63,7 @@ pub enum DecodeError { pub struct BadMessage; impl From for DecodeError { - fn from(_: BadMessage) -> Self { - Self::BadMessage - } + fn from(_: BadMessage) -> Self { Self::BadMessage } } impl core::fmt::Debug for DecodeError { diff --git a/common/proto-utils/src/tests.rs b/common/proto-utils/src/tests.rs index 863deb6a..19c5ec69 100644 --- a/common/proto-utils/src/tests.rs +++ b/common/proto-utils/src/tests.rs @@ -10,13 +10,9 @@ pub mod pb { const NAME: &'static str = "Message"; const PACKAGE: &'static str = "foo"; - fn full_name() -> ::alloc::string::String { - "foo.Message".into() - } + fn full_name() -> ::alloc::string::String { "foo.Message".into() } - fn type_url() -> ::alloc::string::String { - "/foo.Message".into() - } + fn type_url() -> ::alloc::string::String { "/foo.Message".into() } } } } diff --git a/common/sealable-trie/src/bits.rs b/common/sealable-trie/src/bits.rs index 7a3ff841..94262159 100644 --- a/common/sealable-trie/src/bits.rs +++ b/common/sealable-trie/src/bits.rs @@ -107,23 +107,19 @@ impl<'a> Slice<'a> { let used = slice.bytes(); let first = used.first().copied().unwrap_or_default(); let last = used.last().copied().unwrap_or_default(); - (first & !front) == 0 - && (last & !back) == 0 - && bytes[used.len()..].iter().all(|&b| b == 0) + (first & !front) == 0 && + (last & !back) == 0 && + bytes[used.len()..].iter().all(|&b| b == 0) }) } /// Returns length of the slice in bits. #[inline] - pub fn len(&self) -> u16 { - self.length - } + pub fn len(&self) -> u16 { self.length } /// Returns whether the slice is empty. #[inline] - pub fn is_empty(&self) -> bool { - self.length == 0 - } + pub fn is_empty(&self) -> bool { self.length == 0 } /// Returns the first bit in the slice advances the slice by one position. /// @@ -242,9 +238,7 @@ impl<'a> Slice<'a> { /// may be shorter than 272 bits (i.e. 34 * 8) however it will span full 34 /// bytes. #[inline] - pub fn chunks(&self) -> Chunks<'a> { - Chunks::new(*self) - } + pub fn chunks(&self) -> Chunks<'a> { Chunks::new(*self) } /// Splits slice into two at given index. /// @@ -450,9 +444,7 @@ impl<'a> Slice<'a> { /// Calculates underlying bytes length of the slice. #[inline] - fn bytes_len(&self) -> usize { - bytes_len(self.offset, self.length) - } + fn bytes_len(&self) -> usize { bytes_len(self.offset, self.length) } /// Helper method which returns masks for leading and trailing byte. /// @@ -500,9 +492,7 @@ impl From> for Owned { } impl From> for Owned { - fn from(key: ExtKey<'_>) -> Self { - Self::from(Slice::from(key)) - } + fn from(key: ExtKey<'_>) -> Self { Self::from(Slice::from(key)) } } impl Owned { @@ -527,15 +517,11 @@ impl Owned { /// Returns length of the slice in bits. #[inline] - pub fn len(&self) -> u16 { - self.length - } + pub fn len(&self) -> u16 { self.length } /// Returns whether the slice is empty. #[inline] - pub fn is_empty(&self) -> bool { - self.length == 0 - } + pub fn is_empty(&self) -> bool { self.length == 0 } /// Borrows the owned slice. pub fn as_slice(&self) -> Slice { @@ -754,32 +740,26 @@ impl core::cmp::PartialEq for Slice<'_> { if len == 1 { ((lhs[0] ^ rhs[0]) & front & back) == 0 } else { - ((lhs[0] ^ rhs[0]) & front) == 0 - && ((lhs[len - 1] ^ rhs[len - 1]) & back) == 0 - && lhs[1..len - 1] == rhs[1..len - 1] + ((lhs[0] ^ rhs[0]) & front) == 0 && + ((lhs[len - 1] ^ rhs[len - 1]) & back) == 0 && + lhs[1..len - 1] == rhs[1..len - 1] } } } impl core::cmp::PartialEq for Owned { #[inline] - fn eq(&self, other: &Self) -> bool { - self.as_slice() == other.as_slice() - } + fn eq(&self, other: &Self) -> bool { self.as_slice() == other.as_slice() } } impl core::cmp::PartialEq> for Owned { #[inline] - fn eq(&self, other: &Slice) -> bool { - &self.as_slice() == other - } + fn eq(&self, other: &Slice) -> bool { &self.as_slice() == other } } impl core::cmp::PartialEq for Slice<'_> { #[inline] - fn eq(&self, other: &Owned) -> bool { - self == &other.as_slice() - } + fn eq(&self, other: &Owned) -> bool { self == &other.as_slice() } } impl TryFrom> for Vec { diff --git a/common/sealable-trie/src/bits/concat.rs b/common/sealable-trie/src/bits/concat.rs index 7082d570..602bf8be 100644 --- a/common/sealable-trie/src/bits/concat.rs +++ b/common/sealable-trie/src/bits/concat.rs @@ -79,15 +79,11 @@ pub enum Error { } impl From for Error { - fn from(_: SliceTooLong) -> Error { - Error::SliceTooLong - } + fn from(_: SliceTooLong) -> Error { Error::SliceTooLong } } impl From for Error { - fn from(_: MisalignedSlice) -> Error { - Error::Misaligned - } + fn from(_: MisalignedSlice) -> Error { Error::Misaligned } } pub trait Concat { diff --git a/common/sealable-trie/src/bits/ext_key.rs b/common/sealable-trie/src/bits/ext_key.rs index 4994e170..21f284b8 100644 --- a/common/sealable-trie/src/bits/ext_key.rs +++ b/common/sealable-trie/src/bits/ext_key.rs @@ -43,15 +43,11 @@ impl<'a> ExtKey<'a> { /// Returns length of the slice in bits. #[inline] - pub fn len(&self) -> u16 { - self.0.len() - } + pub fn len(&self) -> u16 { self.0.len() } /// Converts the object into underlying [`Slice`]. #[inline] - pub fn into_slice(self) -> Slice<'a> { - self.0 - } + pub fn into_slice(self) -> Slice<'a> { self.0 } /// Encodes key into raw binary representation. /// @@ -104,9 +100,7 @@ impl<'a> ExtKey<'a> { impl<'a> Chunks<'a> { /// Constructs a new `Chunks` iterator over given bit slice. - pub(super) fn new(slice: Slice<'a>) -> Self { - Self(slice) - } + pub(super) fn new(slice: Slice<'a>) -> Self { Self(slice) } } impl<'a> TryFrom> for ExtKey<'a> { diff --git a/common/sealable-trie/src/nodes.rs b/common/sealable-trie/src/nodes.rs index 9ab11e17..c5a230da 100644 --- a/common/sealable-trie/src/nodes.rs +++ b/common/sealable-trie/src/nodes.rs @@ -245,9 +245,7 @@ impl RawNode { } /// Splits the raw byte representation in two halfs. - fn halfs(&self) -> (&[u8; 36], &[u8; 36]) { - stdx::split_array_ref(&self.0) - } + fn halfs(&self) -> (&[u8; 36], &[u8; 36]) { stdx::split_array_ref(&self.0) } /// Splits the raw byte representation in two halfs. fn halfs_mut(&mut self) -> (&mut [u8; 36], &mut [u8; 36]) { @@ -329,9 +327,7 @@ impl<'a> Reference<'a> { impl<'a, P> NodeRef<'a, P> { /// Constructs a new node reference. #[inline] - pub fn new(ptr: P, hash: &'a CryptoHash) -> Self { - Self { ptr, hash } - } + pub fn new(ptr: P, hash: &'a CryptoHash) -> Self { Self { ptr, hash } } } impl<'a, S> ValueRef<'a, S> { diff --git a/common/sealable-trie/src/proof.rs b/common/sealable-trie/src/proof.rs index a844b3ae..3f573d90 100644 --- a/common/sealable-trie/src/proof.rs +++ b/common/sealable-trie/src/proof.rs @@ -98,9 +98,7 @@ impl Proof { } /// Creates a builder which allows creation of proofs. - pub(crate) fn builder() -> Builder { - Builder(Vec::new()) - } + pub(crate) fn builder() -> Builder { Builder(Vec::new()) } } impl Membership { @@ -247,9 +245,7 @@ impl Item { impl Builder { /// Adds a new item to the proof. - pub fn push(&mut self, item: Item) { - self.0.push(item); - } + pub fn push(&mut self, item: Item) { self.0.push(item); } /// Reverses order of items in the builder. /// @@ -263,9 +259,7 @@ impl Builder { } /// Constructs a new membership proof from added items. - pub fn build>(self) -> T { - T::from(Membership(self.0)) - } + pub fn build>(self) -> T { T::from(Membership(self.0)) } /// Constructs a new non-membership proof from added items and given /// ‘actual’ entry. @@ -329,17 +323,11 @@ impl Builder { impl OwnedRef { /// Creates a reference pointing at node with given hash. - fn node(hash: CryptoHash) -> Self { - Self { is_value: false, hash } - } + fn node(hash: CryptoHash) -> Self { Self { is_value: false, hash } } /// Creates a reference pointing at value with given hash. - fn value(hash: CryptoHash) -> Self { - Self { is_value: true, hash } - } + fn value(hash: CryptoHash) -> Self { Self { is_value: true, hash } } /// Creates a reference pointing at given node. - fn to(node: Node) -> Self { - Self::node(node.hash()) - } + fn to(node: Node) -> Self { Self::node(node.hash()) } #[cfg(test)] #[allow(dead_code)] @@ -359,9 +347,7 @@ impl<'a, P, S> From<&'a Reference<'a, P, S>> for OwnedRef { } impl<'a, P, S> From> for OwnedRef { - fn from(rf: Reference<'a, P, S>) -> OwnedRef { - Self::from(&rf) - } + fn from(rf: Reference<'a, P, S>) -> OwnedRef { Self::from(&rf) } } impl<'a> From<&'a OwnedRef> for Reference<'a, (), ()> { diff --git a/common/sealable-trie/src/proof/serialisation.rs b/common/sealable-trie/src/proof/serialisation.rs index a3d7f664..a3e4cdef 100644 --- a/common/sealable-trie/src/proof/serialisation.rs +++ b/common/sealable-trie/src/proof/serialisation.rs @@ -460,19 +460,17 @@ fn test_proof_borsh() { let actual = Actual::LookupKeyLeft(NonZeroU16::MIN, CryptoHash::test(1)); test(Proof::Positive(super::Membership(vec![])), &[0, 0]); - test( - Proof::Positive(super::Membership(vec![item.clone()])), - &[1, 0, 32, 42], - ); + test(Proof::Positive(super::Membership(vec![item.clone()])), &[ + 1, 0, 32, 42, + ]); test( Proof::Positive(super::Membership(vec![item.clone(), item.clone()])), &[2, 0, 32, 42, 32, 42], ); test(Proof::Negative(super::NonMembership(None, vec![])), &[0, 0x80]); - test( - Proof::Negative(super::NonMembership(None, vec![item.clone()])), - &[1, 0x80, 32, 42], - ); + test(Proof::Negative(super::NonMembership(None, vec![item.clone()])), &[ + 1, 0x80, 32, 42, + ]); #[rustfmt::skip] test( Proof::Negative(super::NonMembership( diff --git a/common/sealable-trie/src/trie.rs b/common/sealable-trie/src/trie.rs index 208795df..42efdb3a 100644 --- a/common/sealable-trie/src/trie.rs +++ b/common/sealable-trie/src/trie.rs @@ -96,16 +96,12 @@ pub enum Error { impl From for Error { #[inline] - fn from(_: memory::OutOfMemory) -> Self { - Self::OutOfMemory - } + fn from(_: memory::OutOfMemory) -> Self { Self::OutOfMemory } } impl From for Error { #[inline] - fn from(err: crate::nodes::DecodeError) -> Self { - Self::BadRawNode(err) - } + fn from(err: crate::nodes::DecodeError) -> Self { Self::BadRawNode(err) } } type Result = ::core::result::Result; @@ -130,14 +126,10 @@ impl> Trie { } /// Returns hash of the root node. - pub fn hash(&self) -> &CryptoHash { - &self.root_hash - } + pub fn hash(&self) -> &CryptoHash { &self.root_hash } /// Returns whether the trie is empty. - pub fn is_empty(&self) -> bool { - self.root_hash == EMPTY_TRIE_ROOT - } + pub fn is_empty(&self) -> bool { self.root_hash == EMPTY_TRIE_ROOT } /// Deconstructs the object into the individual parts — allocator, root /// pointer and root hash. diff --git a/common/sealable-trie/src/trie/del.rs b/common/sealable-trie/src/trie/del.rs index 1901ec5e..2ad79f1a 100644 --- a/common/sealable-trie/src/trie/del.rs +++ b/common/sealable-trie/src/trie/del.rs @@ -170,9 +170,7 @@ impl<'a, A: memory::Allocator> Context<'a, A> { } /// Frees a node. - fn del_node(&mut self, ptr: Ptr) { - self.wlog.free(ptr); - } + fn del_node(&mut self, ptr: Ptr) { self.wlog.free(ptr); } /// Converts an [`Action`] into an [`OwnedRef`] if it’s not a `Drop` action. /// diff --git a/common/sealable-trie/src/trie/tests.rs b/common/sealable-trie/src/trie/tests.rs index 22598bae..9c134bcf 100644 --- a/common/sealable-trie/src/trie/tests.rs +++ b/common/sealable-trie/src/trie/tests.rs @@ -162,15 +162,11 @@ fn test_seal_small() { /// Tests using `set_and_seal` to create a trie with all keys sealed. #[cfg(not(miri))] #[test] -fn test_set_and_seal() { - make_trie(false, true); -} +fn test_set_and_seal() { make_trie(false, true); } /// Tests using `set_and_seal` to create a small trie with all keys sealed. #[test] -fn test_set_and_seal_small() { - make_trie(true, true); -} +fn test_set_and_seal_small() { make_trie(true, true); } fn do_test_del((mut trie, keys): (TestTrie, &[u8]), want_mid_count: usize) { let (left, right) = keys.split_at(keys.len() / 2); @@ -187,15 +183,11 @@ fn do_test_del((mut trie, keys): (TestTrie, &[u8]), want_mid_count: usize) { /// Tests deleting all keys of a trie. #[cfg(not(miri))] #[test] -fn test_del() { - do_test_del(make_trie(false, false), 8); -} +fn test_del() { do_test_del(make_trie(false, false), 8); } /// Tests deleting all keys of a small trie. #[test] -fn test_del_small() { - do_test_del(make_trie(true, false), 5); -} +fn test_del_small() { do_test_del(make_trie(true, false), 5); } /// Tests whether deleting a node in between two Extension nodes causes the two /// Extension nodes to be rebalanced. @@ -314,9 +306,7 @@ impl<'a> KeyGen<'a> for RandKeys<'a> { Some(self.generate(known)) } - fn count(&self) -> Option { - Some(self.count) - } + fn count(&self) -> Option { Some(self.count) } } #[test] @@ -402,9 +392,7 @@ struct Key { } impl Key { - fn as_bytes(&self) -> &[u8] { - &self.buf[..usize::from(self.len)] - } + fn as_bytes(&self) -> &[u8] { &self.buf[..usize::from(self.len)] } } impl<'a> From<&'a [u8]> for Key { @@ -421,28 +409,20 @@ impl<'a> From<&'a [u8]> for Key { } impl<'a> From<&'a str> for Key { - fn from(key: &'a str) -> Self { - Self::from(key.as_bytes()) - } + fn from(key: &'a str) -> Self { Self::from(key.as_bytes()) } } impl core::ops::Deref for Key { type Target = [u8]; - fn deref(&self) -> &[u8] { - self.as_bytes() - } + fn deref(&self) -> &[u8] { self.as_bytes() } } impl alloc::borrow::Borrow<[u8]> for Key { - fn borrow(&self) -> &[u8] { - self.as_bytes() - } + fn borrow(&self) -> &[u8] { self.as_bytes() } } impl core::cmp::PartialEq for Key { - fn eq(&self, other: &Self) -> bool { - self.as_bytes() == other.as_bytes() - } + fn eq(&self, other: &Self) -> bool { self.as_bytes() == other.as_bytes() } } impl core::cmp::PartialOrd for Key { @@ -472,26 +452,20 @@ impl<'a, 'b, T: KeyGen<'b>> KeyGen<'b> for &'a mut T { fn next(&mut self, known: &HashMap) -> Option<&'b [u8]> { (**self).next(known) } - fn count(&self) -> Option { - (**self).count() - } + fn count(&self) -> Option { (**self).count() } } struct IterKeyGen(I); impl<'a, I: Iterator> IterKeyGen { - fn new(it: impl IntoIterator) -> Self { - Self(it.into_iter()) - } + fn new(it: impl IntoIterator) -> Self { Self(it.into_iter()) } } impl<'a, I: Iterator> KeyGen<'a> for IterKeyGen { fn next(&mut self, _known: &HashMap) -> Option<&'a [u8]> { self.0.next() } - fn count(&self) -> Option { - self.0.size_hint().1 - } + fn count(&self) -> Option { self.0.size_hint().1 } } struct TestTrie { @@ -509,9 +483,7 @@ impl TestTrie { } } - pub fn hash(&self) -> &CryptoHash { - self.trie.hash() - } + pub fn hash(&self) -> &CryptoHash { self.trie.hash() } pub fn is_empty(&self) -> bool { if self.trie.is_empty() { @@ -522,9 +494,7 @@ impl TestTrie { } } - pub fn nodes_count(&self) -> usize { - self.trie.alloc.count() - } + pub fn nodes_count(&self) -> usize { self.trie.alloc.count() } pub fn set(&mut self, key: &[u8], verbose: bool) { self.try_set(key, verbose).unwrap(); diff --git a/common/trie-ids/src/ids.rs b/common/trie-ids/src/ids.rs index 2b54414a..55da8f33 100644 --- a/common/trie-ids/src/ids.rs +++ b/common/trie-ids/src/ids.rs @@ -84,9 +84,7 @@ impl<'a> TryFrom<&'a ibc::ClientId> for ClientIdx { impl PartialEq for ClientIdx { #[inline] - fn eq(&self, rhs: &usize) -> bool { - usize::from(*self) == *rhs - } + fn eq(&self, rhs: &usize) -> bool { usize::from(*self) == *rhs } } // ==== Connection Id ========================================================== @@ -150,16 +148,12 @@ impl TryFrom<&ibc::ConnectionId> for ConnectionIdx { impl From for ibc::ConnectionId { #[inline] - fn from(idx: ConnectionIdx) -> Self { - Self::new(u64::from(idx)) - } + fn from(idx: ConnectionIdx) -> Self { Self::new(u64::from(idx)) } } impl From<&ConnectionIdx> for ibc::ConnectionId { #[inline] - fn from(idx: &ConnectionIdx) -> Self { - Self::new(u64::from(*idx)) - } + fn from(idx: &ConnectionIdx) -> Self { Self::new(u64::from(*idx)) } } impl fmt::Debug for ConnectionIdx { @@ -231,16 +225,12 @@ impl TryFrom<&ibc::ChannelId> for ChannelIdx { impl From for ibc::ChannelId { #[inline] - fn from(idx: ChannelIdx) -> Self { - Self::new(u64::from(idx)) - } + fn from(idx: ChannelIdx) -> Self { Self::new(u64::from(idx)) } } impl From<&ChannelIdx> for ibc::ChannelId { #[inline] - fn from(idx: &ChannelIdx) -> Self { - Self::new(u64::from(*idx)) - } + fn from(idx: &ChannelIdx) -> Self { Self::new(u64::from(*idx)) } } impl fmt::Debug for ChannelIdx { @@ -277,9 +267,7 @@ impl PortKey { /// Borrows the type as underlying byte array. #[inline] - pub fn as_bytes(&self) -> &[u8; 9] { - &self.0 - } + pub fn as_bytes(&self) -> &[u8; 9] { &self.0 } /// Formats the port identifier in the buffer and returns reference to it as /// a string. @@ -339,9 +327,7 @@ impl TryFrom<&ibc::PortId> for PortKey { } impl From for ibc::PortId { - fn from(port_key: PortKey) -> Self { - Self::from(&port_key) - } + fn from(port_key: PortKey) -> Self { Self::from(&port_key) } } impl From<&PortKey> for ibc::PortId { @@ -436,9 +422,7 @@ impl PortChannelPK { }) } - pub fn port_id(&self) -> ibc::PortId { - ibc::PortId::from(&self.port_key) - } + pub fn port_id(&self) -> ibc::PortId { ibc::PortId::from(&self.port_key) } pub fn channel_id(&self) -> ibc::ChannelId { ibc::ChannelId::new(self.channel_idx.into()) @@ -451,21 +435,13 @@ pub trait MaybeOwned { } impl MaybeOwned for &T { - fn as_ref(&self) -> &T { - self - } - fn into_owned(self) -> T { - (*self).clone() - } + fn as_ref(&self) -> &T { self } + fn into_owned(self) -> T { (*self).clone() } } impl MaybeOwned for T { - fn as_ref(&self) -> &T { - self - } - fn into_owned(self) -> T { - self - } + fn as_ref(&self) -> &T { self } + fn into_owned(self) -> T { self } } // ==== Counter (inetrnal) ===================================================== @@ -525,9 +501,7 @@ impl Counter { impl From for usize { #[inline] - fn from(cnt: Counter) -> usize { - cnt.0 as usize - } + fn from(cnt: Counter) -> usize { cnt.0 as usize } } impl core::fmt::Debug for Counter { diff --git a/common/trie-ids/src/path_info.rs b/common/trie-ids/src/path_info.rs index d9f3f76b..7fdfe214 100644 --- a/common/trie-ids/src/path_info.rs +++ b/common/trie-ids/src/path_info.rs @@ -40,9 +40,7 @@ pub enum SequenceKind { } impl From for usize { - fn from(kind: SequenceKind) -> usize { - kind as usize - } + fn from(kind: SequenceKind) -> usize { kind as usize } } /// Error when converting IBC path into a trie key. diff --git a/common/trie-ids/src/trie_key.rs b/common/trie-ids/src/trie_key.rs index 41d4fdbd..82c12831 100644 --- a/common/trie-ids/src/trie_key.rs +++ b/common/trie-ids/src/trie_key.rs @@ -49,9 +49,7 @@ pub enum Tag { } impl From for u8 { - fn from(tag: Tag) -> u8 { - tag as u8 - } + fn from(tag: Tag) -> u8 { tag as u8 } } /// A discriminant used to distinguish client state and consensus state upgrade @@ -64,9 +62,7 @@ enum UpgradeType { } impl From for u8 { - fn from(ty: UpgradeType) -> u8 { - ty as u8 - } + fn from(ty: UpgradeType) -> u8 { ty as u8 } } impl TrieKey { @@ -186,9 +182,7 @@ impl TrieKey { impl core::ops::Deref for TrieKey { type Target = [u8]; - fn deref(&self) -> &[u8] { - &self.bytes[..usize::from(self.len)] - } + fn deref(&self) -> &[u8] { &self.bytes[..usize::from(self.len)] } } impl core::fmt::Display for TrieKey { @@ -356,16 +350,12 @@ impl AsComponent for UpgradeType { impl AsComponent for [u8; N] { #[inline] - fn append_into(&self, dest: &mut TrieKey) { - dest.extend(self); - } + fn append_into(&self, dest: &mut TrieKey) { dest.extend(self); } } impl AsComponent for &T { #[inline] - fn append_into(&self, dest: &mut TrieKey) { - (*self).append_into(dest) - } + fn append_into(&self, dest: &mut TrieKey) { (*self).append_into(dest) } } impl AsComponent for (T, U) { diff --git a/common/wasm/src/consensus_state.rs b/common/wasm/src/consensus_state.rs index ebfef7cd..3623319d 100644 --- a/common/wasm/src/consensus_state.rs +++ b/common/wasm/src/consensus_state.rs @@ -40,9 +40,7 @@ impl From for proto::ConsensusState { } impl From<&ConsensusState> for proto::ConsensusState { - fn from(state: &ConsensusState) -> Self { - Self::from(state.clone()) - } + fn from(state: &ConsensusState) -> Self { Self::from(state.clone()) } } impl TryFrom for ConsensusState { diff --git a/solana/allocator/src/lib.rs b/solana/allocator/src/lib.rs index ff5f01dd..c69b426f 100644 --- a/solana/allocator/src/lib.rs +++ b/solana/allocator/src/lib.rs @@ -142,9 +142,7 @@ impl BumpAllocator { /// /// Note that by default `G` is a unit type which means that there is no /// reserved global state. - pub fn global(&self) -> &G { - &self.header().global - } + pub fn global(&self) -> &G { &self.header().global } } unsafe impl GlobalAlloc for BumpAllocator { diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 2caf978c..dd5c8d2b 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -394,7 +394,7 @@ pub struct Intent { // Timestamp when the intent was created pub creation_timestamp_in_sec: u64, pub timeout_timestamp_in_sec: u64, - pub single_domain: bool + pub single_domain: bool, } // Define the context for initializing the program diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index df2e3c19..8c2aefd0 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -42,7 +42,8 @@ fn airdrop(client: &RpcClient, account: Pubkey, lamports: u64) -> Signature { #[ignore = "Requires local validator to run"] fn escrow_bridge_program() -> Result<()> { // Setup the client and wallet - let auctioneer = Rc::new(read_keypair_file("../../../solana-ibc/keypair.json").unwrap()); + let auctioneer = + Rc::new(read_keypair_file("../../../solana-ibc/keypair.json").unwrap()); let client = Client::new_with_options( Cluster::Localnet, @@ -383,17 +384,17 @@ fn escrow_bridge_program() -> Result<()> { sol_rpc_client.get_token_account_balance(&user_token_out_addr).unwrap(); assert_eq!( - ((solver_token_in_balance_after.ui_amount.unwrap() - - solver_token_in_balance_before.ui_amount.unwrap()) - * 1_000_000f64) + ((solver_token_in_balance_after.ui_amount.unwrap() - + solver_token_in_balance_before.ui_amount.unwrap()) * + 1_000_000f64) .round() as u64, TRANSFER_AMOUNT ); assert_eq!( - ((user_token_out_balance_after.ui_amount.unwrap() - - user_token_out_balance_before.ui_amount.unwrap()) - * 1_000_000f64) + ((user_token_out_balance_after.ui_amount.unwrap() - + user_token_out_balance_before.ui_amount.unwrap()) * + 1_000_000f64) .round() as u64, amount_out ); diff --git a/solana/restaking/programs/restaking/src/lib.rs b/solana/restaking/programs/restaking/src/lib.rs index 0136a217..717fc5f2 100644 --- a/solana/restaking/programs/restaking/src/lib.rs +++ b/solana/restaking/programs/restaking/src/lib.rs @@ -305,14 +305,14 @@ pub mod restaking { return Err(error!(ErrorCodes::InvalidWithdrawer)); } - if ctx.accounts.withdrawer_token_account.key() - != withdrawal_request_params.token_account + if ctx.accounts.withdrawer_token_account.key() != + withdrawal_request_params.token_account { return Err(error!(ErrorCodes::InvalidTokenAccount)); }; - let unbonding_period = withdrawal_request_params.timestamp_in_sec - + UNBONDING_PERIOD_IN_SEC; + let unbonding_period = withdrawal_request_params.timestamp_in_sec + + UNBONDING_PERIOD_IN_SEC; let current_timestamp = Clock::get()?.unix_timestamp as u64; msg!( diff --git a/solana/restaking/programs/restaking/src/token.rs b/solana/restaking/programs/restaking/src/token.rs index c547bb3a..3c7bfc1a 100644 --- a/solana/restaking/programs/restaking/src/token.rs +++ b/solana/restaking/programs/restaking/src/token.rs @@ -49,14 +49,11 @@ pub fn transfer( /// we dont need signed invocation. pub fn mint_nft(accounts: MintNftAccounts<'_>) -> Result<()> { mint_to( - CpiContext::new( - accounts.token_program.clone(), - MintTo { - authority: accounts.mint_authority.clone(), - to: accounts.to, - mint: accounts.token_mint.clone(), - }, - ), + CpiContext::new(accounts.token_program.clone(), MintTo { + authority: accounts.mint_authority.clone(), + to: accounts.to, + mint: accounts.token_mint.clone(), + }), 1, // 1 token )?; @@ -90,20 +87,17 @@ pub fn mint_nft(accounts: MintNftAccounts<'_>) -> Result<()> { msg!("Run create master edition v3"); create_master_edition_v3( - CpiContext::new( - accounts.metadata_program, - CreateMasterEditionV3 { - edition: accounts.edition, - mint: accounts.token_mint, - update_authority: accounts.update_authority, - mint_authority: accounts.mint_authority, - payer: accounts.payer, - metadata: accounts.metadata, - token_program: accounts.token_program, - system_program: accounts.system_program, - rent: accounts.rent, - }, - ), + CpiContext::new(accounts.metadata_program, CreateMasterEditionV3 { + edition: accounts.edition, + mint: accounts.token_mint, + update_authority: accounts.update_authority, + mint_authority: accounts.mint_authority, + payer: accounts.payer, + metadata: accounts.metadata, + token_program: accounts.token_program, + system_program: accounts.system_program, + rent: accounts.rent, + }), Some(1), )?; Ok(()) diff --git a/solana/signature-verifier/src/api.rs b/solana/signature-verifier/src/api.rs index 6b1d1883..ec1fd351 100644 --- a/solana/signature-verifier/src/api.rs +++ b/solana/signature-verifier/src/api.rs @@ -55,9 +55,7 @@ impl SignatureHash { } impl AsRef<[u8; 32]> for SignatureHash { - fn as_ref(&self) -> &[u8; 32] { - &self.0 - } + fn as_ref(&self) -> &[u8; 32] { &self.0 } } impl<'a> From> for SignatureHash { diff --git a/solana/signature-verifier/src/ed25519.rs b/solana/signature-verifier/src/ed25519.rs index 76413c6b..9b40c5ce 100644 --- a/solana/signature-verifier/src/ed25519.rs +++ b/solana/signature-verifier/src/ed25519.rs @@ -42,9 +42,7 @@ impl From for PubKey { } impl From for solana_program::pubkey::Pubkey { - fn from(pubkey: PubKey) -> Self { - Self::from(pubkey.0) - } + fn from(pubkey: PubKey) -> Self { Self::from(pubkey.0) } } impl PartialEq for PubKey { @@ -54,9 +52,7 @@ impl PartialEq for PubKey { } impl PartialEq for solana_program::pubkey::Pubkey { - fn eq(&self, other: &PubKey) -> bool { - self.as_ref() == &other.0[..] - } + fn eq(&self, other: &PubKey) -> bool { self.as_ref() == &other.0[..] } } #[cfg(feature = "guest")] @@ -64,9 +60,7 @@ impl guestchain::PubKey for PubKey { type Signature = Signature; #[inline] - fn as_bytes(&self) -> alloc::borrow::Cow<'_, [u8]> { - (&self.0[..]).into() - } + fn as_bytes(&self) -> alloc::borrow::Cow<'_, [u8]> { (&self.0[..]).into() } #[inline] fn from_bytes(bytes: &[u8]) -> Result { Ok(Self(bytes.try_into()?)) @@ -108,9 +102,7 @@ impl<'a> TryFrom<&'a [u8]> for &'a Signature { #[cfg(feature = "guest")] impl guestchain::Signature for Signature { #[inline] - fn as_bytes(&self) -> alloc::borrow::Cow<'_, [u8]> { - (&self.0[..]).into() - } + fn as_bytes(&self) -> alloc::borrow::Cow<'_, [u8]> { (&self.0[..]).into() } #[inline] fn from_bytes(bytes: &[u8]) -> Result { Ok(Self(bytes.try_into()?)) diff --git a/solana/signature-verifier/src/ed25519_program.rs b/solana/signature-verifier/src/ed25519_program.rs index 90642fe7..aaff3458 100644 --- a/solana/signature-verifier/src/ed25519_program.rs +++ b/solana/signature-verifier/src/ed25519_program.rs @@ -219,21 +219,15 @@ pub enum Error { pub struct BadData; impl From for Error { - fn from(_: BadData) -> Self { - Self::BadData - } + fn from(_: BadData) -> Self { Self::BadData } } impl From for solana_program::program_error::ProgramError { - fn from(_: BadData) -> Self { - Self::InvalidInstructionData - } + fn from(_: BadData) -> Self { Self::InvalidInstructionData } } impl From for solana_program::program_error::ProgramError { - fn from(_: Error) -> Self { - Self::InvalidInstructionData - } + fn from(_: Error) -> Self { Self::InvalidInstructionData } } /// An item returned by th @@ -253,9 +247,9 @@ fn decode_entry<'a>(data: &'a [u8], entry: &'a [u8; 14]) -> Item<'a> { let [sig_offset, sig_ix_idx, key_offset, key_ix_idx, msg_offset, msg_size, msg_ix_idx] = entry; - if sig_ix_idx != u16::MAX - || key_ix_idx != u16::MAX - || msg_ix_idx != u16::MAX + if sig_ix_idx != u16::MAX || + key_ix_idx != u16::MAX || + msg_ix_idx != u16::MAX { return Err(Error::UnsupportedFeature); } @@ -298,18 +292,12 @@ impl<'a> core::iter::Iterator for Iter<'a> { Some(decode_entry(self.data, entry)) } - fn size_hint(&self) -> (usize, Option) { - self.entries.size_hint() - } - fn count(self) -> usize { - self.entries.count() - } + fn size_hint(&self) -> (usize, Option) { self.entries.size_hint() } + fn count(self) -> usize { self.entries.count() } } impl<'a> core::iter::ExactSizeIterator for Iter<'a> { - fn len(&self) -> usize { - self.entries.len() - } + fn len(&self) -> usize { self.entries.len() } } impl<'a> core::iter::DoubleEndedIterator for Iter<'a> { diff --git a/solana/signature-verifier/src/verifier.rs b/solana/signature-verifier/src/verifier.rs index 0e628d3f..ea5c2546 100644 --- a/solana/signature-verifier/src/verifier.rs +++ b/solana/signature-verifier/src/verifier.rs @@ -55,9 +55,7 @@ impl<'info> Default for Verifier<'info> { /// sigverify program (see [`Self::set_sigverify_account`]). Unless at /// least on of those is initialised, the verifier will reject all /// signatures. - fn default() -> Self { - Self { ed25519_data: None, sigverify_data: None } - } + fn default() -> Self { Self { ed25519_data: None, sigverify_data: None } } } impl<'info> Verifier<'info> { @@ -163,9 +161,7 @@ fn check_sigverify_data(data: &[u8], entry: &Entry) -> Result { } impl From for Error { - fn from(_: crate::ed25519_program::BadData) -> Self { - Self::BadData - } + fn from(_: crate::ed25519_program::BadData) -> Self { Self::BadData } } impl From for ProgramError { diff --git a/solana/solana-ibc/programs/solana-ibc/src/allocator.rs b/solana/solana-ibc/programs/solana-ibc/src/allocator.rs index 9b387593..e1c1122c 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/allocator.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/allocator.rs @@ -66,9 +66,7 @@ mod imp { }; /// Returns reference to the global state. - pub(crate) fn global() -> &'static Global { - ALLOCATOR.global() - } + pub(crate) fn global() -> &'static Global { ALLOCATOR.global() } } #[cfg(any( diff --git a/solana/solana-ibc/programs/solana-ibc/src/chain.rs b/solana/solana-ibc/programs/solana-ibc/src/chain.rs index 5e81f7b0..24fda8fe 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/chain.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/chain.rs @@ -427,21 +427,15 @@ fn get_host_head() -> Result<(guestchain::HostHeight, NonZeroU64)> { } impl From for Error { - fn from(_: ChainNotInitialised) -> Self { - Error::ChainNotInitialised - } + fn from(_: ChainNotInitialised) -> Self { Error::ChainNotInitialised } } impl From for anchor_lang::error::AnchorError { - fn from(err: ChainNotInitialised) -> Self { - Error::from(err).into() - } + fn from(err: ChainNotInitialised) -> Self { Error::from(err).into() } } impl From for anchor_lang::error::Error { - fn from(err: ChainNotInitialised) -> Self { - Error::from(err).into() - } + fn from(err: ChainNotInitialised) -> Self { Error::from(err).into() } } impl From for ibc::ClientError { diff --git a/solana/solana-ibc/programs/solana-ibc/src/client_state/impls.rs b/solana/solana-ibc/programs/solana-ibc/src/client_state/impls.rs index 40d5d920..3a9357f5 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/client_state/impls.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/client_state/impls.rs @@ -232,9 +232,7 @@ mod tm { ProvidedVotingPowerCalculator, ProdCommitValidator, >; - fn verifier(&self) -> Self::Verifier { - Default::default() - } + fn verifier(&self) -> Self::Verifier { Default::default() } } impl VerificationPredicates for InnerProdPredicates { @@ -291,21 +289,11 @@ impl ibc::HostFunctionsProvider for SolanaHostFunctions { unimplemented!() } - fn sha2_512(_message: &[u8]) -> [u8; 64] { - unimplemented!() - } - fn sha2_512_truncated(_message: &[u8]) -> [u8; 32] { - unimplemented!() - } - fn ripemd160(_message: &[u8]) -> [u8; 20] { - unimplemented!() - } - fn blake2b_512(_message: &[u8]) -> [u8; 64] { - unimplemented!() - } - fn blake2s_256(_message: &[u8]) -> [u8; 32] { - unimplemented!() - } + fn sha2_512(_message: &[u8]) -> [u8; 64] { unimplemented!() } + fn sha2_512_truncated(_message: &[u8]) -> [u8; 32] { unimplemented!() } + fn ripemd160(_message: &[u8]) -> [u8; 20] { unimplemented!() } + fn blake2b_512(_message: &[u8]) -> [u8; 64] { unimplemented!() } + fn blake2s_256(_message: &[u8]) -> [u8; 32] { unimplemented!() } } #[cfg(all(test, not(miri)))] diff --git a/solana/solana-ibc/programs/solana-ibc/src/error.rs b/solana/solana-ibc/programs/solana-ibc/src/error.rs index 6079ab3b..3a92019e 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/error.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/error.rs @@ -132,12 +132,10 @@ pub enum Error { } impl Error { - pub fn name(&self) -> String { - <&'static str>::from(self).into() - } + pub fn name(&self) -> String { <&'static str>::from(self).into() } pub fn code(&self) -> u32 { - anchor_lang::error::ERROR_CODE_OFFSET - + ErrorDiscriminants::from(self) as u32 + anchor_lang::error::ERROR_CODE_OFFSET + + ErrorDiscriminants::from(self) as u32 } } @@ -153,21 +151,15 @@ impl core::fmt::Display for Error { } impl From for u32 { - fn from(err: Error) -> u32 { - err.code() - } + fn from(err: Error) -> u32 { err.code() } } impl From<&Error> for u32 { - fn from(err: &Error) -> u32 { - err.code() - } + fn from(err: &Error) -> u32 { err.code() } } impl From for Error { - fn from(_: manager::BadGenesis) -> Self { - Self::Internal("BadGenesis") - } + fn from(_: manager::BadGenesis) -> Self { Self::Internal("BadGenesis") } } impl From for Error { diff --git a/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs b/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs index 50e828a9..772eea68 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs @@ -123,9 +123,7 @@ impl ibc::ExecutionContext for IbcStorage<'_, '_> { /// /// The clients are stored in the vector so we can easily find how many /// clients were created. So thats why this method doesnt do anything. - fn increase_client_counter(&mut self) -> Result { - Ok(()) - } + fn increase_client_counter(&mut self) -> Result { Ok(()) } fn store_connection( &mut self, @@ -178,9 +176,7 @@ impl ibc::ExecutionContext for IbcStorage<'_, '_> { /// /// Connections are stored in a vector in an order, so the length of the /// array specifies the number of connections. - fn increase_connection_counter(&mut self) -> Result { - Ok(()) - } + fn increase_connection_counter(&mut self) -> Result { Ok(()) } fn store_packet_commitment( &mut self, @@ -300,9 +296,7 @@ impl ibc::ExecutionContext for IbcStorage<'_, '_> { Ok(()) } - fn get_client_execution_context(&mut self) -> &mut Self::E { - self - } + fn get_client_execution_context(&mut self) -> &mut Self::E { self } } impl storage::IbcStorage<'_, '_> { diff --git a/solana/solana-ibc/programs/solana-ibc/src/ix_data_account.rs b/solana/solana-ibc/programs/solana-ibc/src/ix_data_account.rs index 51cf7a65..43d45f8b 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/ix_data_account.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/ix_data_account.rs @@ -73,9 +73,7 @@ use solana_program::pubkey::Pubkey; pub struct Accounts(T, Pubkey); impl Accounts { - pub fn new(accounts: T, ix_data: Pubkey) -> Self { - Self(accounts, ix_data) - } + pub fn new(accounts: T, ix_data: Pubkey) -> Self { Self(accounts, ix_data) } } /// An ‘instruction’ which instructs smart contract to read the data from an @@ -117,24 +115,18 @@ pub(crate) fn get_ix_data<'a>( impl anchor_lang::Discriminator for Instruction { const DISCRIMINATOR: [u8; 8] = [0; 8]; - fn discriminator() -> [u8; 8] { - panic!() - } + fn discriminator() -> [u8; 8] { panic!() } } impl borsh::BorshSerialize for Instruction { fn serialize(&self, _writer: &mut W) -> io::Result<()> { Ok(()) } - fn try_to_vec(&self) -> io::Result> { - Ok(Vec::new()) - } + fn try_to_vec(&self) -> io::Result> { Ok(Vec::new()) } } impl anchor_lang::InstructionData for Instruction { - fn data(&self) -> Vec { - Vec::new() - } + fn data(&self) -> Vec { Vec::new() } } #[test] diff --git a/solana/solana-ibc/programs/solana-ibc/src/lib.rs b/solana/solana-ibc/programs/solana-ibc/src/lib.rs index a1b2e80d..f284173e 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/lib.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/lib.rs @@ -284,8 +284,8 @@ pub mod solana_ibc { ) -> Result<()> { let fee_account = &ctx.accounts.fee_account; let minimum_balance = Rent::get()? - .minimum_balance(fee_account.data_len()) - + MINIMUM_FEE_ACCOUNT_BALANCE; + .minimum_balance(fee_account.data_len()) + + MINIMUM_FEE_ACCOUNT_BALANCE; let mut available_balance = fee_account.try_borrow_mut_lamports()?; if **available_balance > minimum_balance { **ctx.accounts.fee_collector.try_borrow_mut_lamports()? += @@ -321,13 +321,10 @@ pub mod solana_ibc { } if !private_storage.assets.contains_key(&hashed_full_denom) { - private_storage.assets.insert( - hashed_full_denom, - storage::Asset { - original_decimals, - effective_decimals_on_sol: effective_decimals, - }, - ); + private_storage.assets.insert(hashed_full_denom, storage::Asset { + original_decimals, + effective_decimals_on_sol: effective_decimals, + }); } else { return Err(error!(error::Error::AssetAlreadyExists)); } @@ -454,8 +451,8 @@ pub mod solana_ibc { let mut token_ctx = store.clone(); // Check if atleast one of the timeouts is non zero. - if !msg.timeout_height_on_b.is_set() - && !msg.timeout_timestamp_on_b.is_set() + if !msg.timeout_height_on_b.is_set() && + !msg.timeout_timestamp_on_b.is_set() { return Err(error::Error::InvalidTimeout.into()); } diff --git a/solana/solana-ibc/programs/solana-ibc/src/storage.rs b/solana/solana-ibc/programs/solana-ibc/src/storage.rs index eb71c5cc..c71e038e 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/storage.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/storage.rs @@ -217,9 +217,7 @@ pub struct ClientRef<'a> { impl<'a> core::ops::Deref for ClientRef<'a> { type Target = ClientStore; - fn deref(&self) -> &ClientStore { - self.store - } + fn deref(&self) -> &ClientStore { self.store } } /// An exclusive reference to a [`ClientStore`] together with its index. @@ -230,15 +228,11 @@ pub struct ClientMut<'a> { impl<'a> core::ops::Deref for ClientMut<'a> { type Target = ClientStore; - fn deref(&self) -> &ClientStore { - self.store - } + fn deref(&self) -> &ClientStore { self.store } } impl<'a> core::ops::DerefMut for ClientMut<'a> { - fn deref_mut(&mut self) -> &mut ClientStore { - self.store - } + fn deref_mut(&mut self) -> &mut ClientStore { self.store } } #[derive(Clone, Debug, borsh::BorshSerialize, borsh::BorshDeserialize)] @@ -580,21 +574,15 @@ pub(crate) use from_ctx; pub struct Serialised(Vec, core::marker::PhantomData); impl Serialised { - pub fn empty() -> Self { - Self(Vec::new(), core::marker::PhantomData) - } + pub fn empty() -> Self { Self(Vec::new(), core::marker::PhantomData) } - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } + pub fn is_empty(&self) -> bool { self.0.is_empty() } pub fn transmute(self) -> Serialised { Serialised(self.0, core::marker::PhantomData) } - pub fn as_bytes(&self) -> &[u8] { - self.0.as_slice() - } + pub fn as_bytes(&self) -> &[u8] { self.0.as_slice() } } impl Serialised { diff --git a/solana/solana-ibc/programs/solana-ibc/src/storage/map.rs b/solana/solana-ibc/programs/solana-ibc/src/storage/map.rs index f969618e..4f7761b5 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/storage/map.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/storage/map.rs @@ -11,9 +11,7 @@ use anchor_lang::prelude::borsh::maybestd::io; pub struct Map(linear_map::LinearMap); impl Default for Map { - fn default() -> Self { - Self(Default::default()) - } + fn default() -> Self { Self(Default::default()) } } impl fmt::Debug for Map { @@ -23,15 +21,11 @@ impl fmt::Debug for Map { } impl From> for Map { - fn from(entries: Vec<(K, V)>) -> Self { - Self(entries.into()) - } + fn from(entries: Vec<(K, V)>) -> Self { Self(entries.into()) } } impl From> for Vec<(K, V)> { - fn from(map: Map) -> Self { - Self::from(map.0) - } + fn from(map: Map) -> Self { Self::from(map.0) } } impl borsh::BorshSerialize for Map diff --git a/solana/solana-ibc/programs/solana-ibc/src/tests.rs b/solana/solana-ibc/programs/solana-ibc/src/tests.rs index 62abea6e..77abd998 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/tests.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/tests.rs @@ -555,9 +555,9 @@ fn anchor_test_deliver() -> Result<()> { sol_rpc_client.get_balance(&fee_collector_pda).unwrap(); assert_eq!( - ((account_balance_before.ui_amount.unwrap() - - account_balance_after.ui_amount.unwrap()) - * 1_000_000_000f64) + ((account_balance_before.ui_amount.unwrap() - + account_balance_after.ui_amount.unwrap()) * + 1_000_000_000f64) .round() as u64, TRANSFER_AMOUNT ); @@ -632,11 +632,11 @@ fn anchor_test_deliver() -> Result<()> { .get_token_account_balance(&receiver_token_address) .unwrap(); assert_eq!( - ((account_balance_after.ui_amount.unwrap() - account_balance_before) - * 10_f64.powf(mint_info.decimals.into())) + ((account_balance_after.ui_amount.unwrap() - account_balance_before) * + 10_f64.powf(mint_info.decimals.into())) .round() as u64, - TRANSFER_AMOUNT - / (10_u64.pow((ORIGINAL_DECIMALS - EFFECTIVE_DECIMALS).into())) + TRANSFER_AMOUNT / + (10_u64.pow((ORIGINAL_DECIMALS - EFFECTIVE_DECIMALS).into())) ); /* @@ -708,12 +708,12 @@ fn anchor_test_deliver() -> Result<()> { sol_rpc_client.get_balance(&fee_collector_pda).unwrap(); assert_eq!( - ((account_balance_before.ui_amount.unwrap() - - account_balance_after.ui_amount.unwrap()) - * 10_f64.powf(mint_info.decimals.into())) + ((account_balance_before.ui_amount.unwrap() - + account_balance_after.ui_amount.unwrap()) * + 10_f64.powf(mint_info.decimals.into())) .round() as u64, - TRANSFER_AMOUNT - / (10_u64.pow((ORIGINAL_DECIMALS - EFFECTIVE_DECIMALS).into())) + TRANSFER_AMOUNT / + (10_u64.pow((ORIGINAL_DECIMALS - EFFECTIVE_DECIMALS).into())) ); assert_eq!(fee_account_balance_after - fee_account_balance_before, FEE); diff --git a/solana/solana-ibc/programs/solana-ibc/src/transfer/impls.rs b/solana/solana-ibc/programs/solana-ibc/src/transfer/impls.rs index 2e2e92ec..341843ac 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/transfer/impls.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/transfer/impls.rs @@ -306,9 +306,9 @@ impl TokenTransferValidationContext for IbcStorage<'_, '_> { let store = self.borrow(); let accounts = &store.accounts; - if accounts.token_program.is_none() - || accounts.token_mint.is_none() - || accounts.mint_authority.is_none() + if accounts.token_program.is_none() || + accounts.token_mint.is_none() || + accounts.mint_authority.is_none() { return Err(TokenTransferError::ParseAccountFailure); } @@ -369,9 +369,9 @@ impl TokenTransferValidationContext for IbcStorage<'_, '_> { let token_mint = get_token_mint(&coin.denom)?; let store = self.borrow(); let accounts = &store.accounts; - if accounts.token_program.is_none() - || accounts.token_mint.is_none() - || accounts.mint_authority.is_none() + if accounts.token_program.is_none() || + accounts.token_mint.is_none() || + accounts.mint_authority.is_none() { return Err(TokenTransferError::ParseAccountFailure); } @@ -534,8 +534,8 @@ impl IbcStorage<'_, '_> { // Close the wsol account so that the receiver gets the amount in native SOL // instead of wrapped SOL which is unusable if the wallet doesnt have any // SOL to pay for the fees. - if matches!(op, EscrowOp::Unescrow) - && coin.denom.base_denom.as_str() == crate::WSOL_ADDRESS + if matches!(op, EscrowOp::Unescrow) && + coin.denom.base_denom.as_str() == crate::WSOL_ADDRESS { let receiver = accounts .receiver @@ -566,8 +566,8 @@ impl IbcStorage<'_, '_> { // Closing the wsol account after transferring the amount to the escrow // so that the escrow account holds the wsol deposits in native SOL which // can be transferred to the receiver instead of sending wrapped sol. - if matches!(op, EscrowOp::Escrow) - && coin.denom.base_denom.as_str() == crate::WSOL_ADDRESS + if matches!(op, EscrowOp::Escrow) && + coin.denom.base_denom.as_str() == crate::WSOL_ADDRESS { let mint_authority = accounts .mint_authority diff --git a/solana/solana-ibc/programs/solana-ibc/src/validation_context.rs b/solana/solana-ibc/programs/solana-ibc/src/validation_context.rs index cc452575..44fba5c2 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/validation_context.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/validation_context.rs @@ -250,9 +250,7 @@ impl ibc::ValidationContext for IbcStorage<'_, '_> { } } - fn get_client_validation_context(&self) -> &Self::V { - self - } + fn get_client_validation_context(&self) -> &Self::V { self } fn get_compatible_versions(&self) -> Vec { ibc::conn::get_compatible_versions() @@ -365,7 +363,7 @@ fn calculate_block_delay( if max_expected_time_per_block.is_zero() { return 0; } - let delay = delay_period_time.as_secs_f64() - / max_expected_time_per_block.as_secs_f64(); + let delay = delay_period_time.as_secs_f64() / + max_expected_time_per_block.as_secs_f64(); delay.ceil() as u64 } diff --git a/solana/trie/src/account.rs b/solana/trie/src/account.rs index f59b98ed..2dc06106 100644 --- a/solana/trie/src/account.rs +++ b/solana/trie/src/account.rs @@ -48,14 +48,10 @@ impl<'a, 'info> ResizableAccount<'a, 'info> { impl<'a, 'info> crate::data_ref::DataRef for ResizableAccount<'a, 'info> { #[inline] - fn len(&self) -> usize { - self.get(..).map_or(0, |bytes| bytes.len()) - } + fn len(&self) -> usize { self.get(..).map_or(0, |bytes| bytes.len()) } #[inline] - fn is_empty(&self) -> bool { - self.len() == 0 - } + fn is_empty(&self) -> bool { self.len() == 0 } fn get>(&self, index: I) -> Option<&I::Output> { unsafe fn transmute_lifetime<'a, T: ?Sized>(arg: &T) -> &'a T { diff --git a/solana/trie/src/alloc.rs b/solana/trie/src/alloc.rs index 08f35399..f812eeb6 100644 --- a/solana/trie/src/alloc.rs +++ b/solana/trie/src/alloc.rs @@ -70,9 +70,7 @@ impl Allocator { pub(crate) struct Addr(NonZeroU32); impl Addr { - fn new(addr: u32) -> Option { - NonZeroU32::new(addr).map(Self) - } + fn new(addr: u32) -> Option { NonZeroU32::new(addr).map(Self) } /// Returns next properly aligned block or `None` if next address would /// overflow. @@ -82,14 +80,10 @@ impl Addr { /// Cast address to `usize` or retuns `None` if the value doesn’t fit. The /// latter only happens on 16-bit systems. - pub fn usize(self) -> Option { - usize::try_from(self.0.get()).ok() - } + pub fn usize(self) -> Option { usize::try_from(self.0.get()).ok() } /// Returns wrapped `u32` value. - pub fn u32(self) -> u32 { - self.0.get() - } + pub fn u32(self) -> u32 { self.0.get() } /// Returns range of addresses covered by block this address points at. fn range(self) -> core::ops::Range { diff --git a/solana/trie/src/data_ref.rs b/solana/trie/src/data_ref.rs index ad73cd08..a1ff3aee 100644 --- a/solana/trie/src/data_ref.rs +++ b/solana/trie/src/data_ref.rs @@ -4,9 +4,7 @@ pub trait DataRef { fn len(&self) -> usize; /// Returns whether the data is empty. - fn is_empty(&self) -> bool { - self.len() == 0 - } + fn is_empty(&self) -> bool { self.len() == 0 } /// Returns a shared reference to a byte or subslice depending on the type /// of index. @@ -33,9 +31,7 @@ pub trait DataRef { impl DataRef for [u8] { #[inline] - fn len(&self) -> usize { - (*self).len() - } + fn len(&self) -> usize { (*self).len() } fn get>( &self, @@ -52,16 +48,12 @@ impl DataRef for [u8] { } #[inline] - fn enlarge(&mut self, _min_size: usize) -> bool { - false - } + fn enlarge(&mut self, _min_size: usize) -> bool { false } } impl DataRef for [u8; N] { #[inline] - fn len(&self) -> usize { - N - } + fn len(&self) -> usize { N } fn get>( &self, @@ -78,16 +70,12 @@ impl DataRef for [u8; N] { } #[inline] - fn enlarge(&mut self, _min_size: usize) -> bool { - false - } + fn enlarge(&mut self, _min_size: usize) -> bool { false } } impl DataRef for Vec { #[inline] - fn len(&self) -> usize { - (**self).len() - } + fn len(&self) -> usize { (**self).len() } fn get>( &self, @@ -118,9 +106,7 @@ impl DataRef for Vec { } impl DataRef for &'_ mut D { - fn len(&self) -> usize { - (**self).len() - } + fn len(&self) -> usize { (**self).len() } fn get>( &self, @@ -144,9 +130,7 @@ impl DataRef for &'_ mut D { impl DataRef for core::cell::RefMut<'_, D> { #[inline] - fn len(&self) -> usize { - (**self).len() - } + fn len(&self) -> usize { (**self).len() } fn get>( &self, @@ -163,7 +147,5 @@ impl DataRef for core::cell::RefMut<'_, D> { } #[inline] - fn enlarge(&mut self, _min_size: usize) -> bool { - false - } + fn enlarge(&mut self, _min_size: usize) -> bool { false } } diff --git a/solana/trie/src/lib.rs b/solana/trie/src/lib.rs index 6772f04a..05a34e30 100644 --- a/solana/trie/src/lib.rs +++ b/solana/trie/src/lib.rs @@ -78,8 +78,8 @@ fn check_account( account: &AccountInfo, owner: &Pubkey, ) -> Result<(), ProgramError> { - if !solana_program::system_program::check_id(account.owner) - && account.lamports() == 0 + if !solana_program::system_program::check_id(account.owner) && + account.lamports() == 0 { Err(ProgramError::UninitializedAccount) } else if account.owner != owner { @@ -109,15 +109,11 @@ impl core::ops::Drop for TrieAccount { impl core::ops::Deref for TrieAccount { type Target = sealable_trie::Trie>; - fn deref(&self) -> &Self::Target { - &self.0 - } + fn deref(&self) -> &Self::Target { &self.0 } } impl core::ops::DerefMut for TrieAccount { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } #[test] diff --git a/validator/src/main.rs b/validator/src/main.rs index f1e04daf..a5bb21c4 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -3,6 +3,4 @@ mod stake; mod utils; mod validator; -fn main() { - command::process_command(); -} +fn main() { command::process_command(); } From aa04971f54240bab24f21e3067af8fa4722df9f6 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Thu, 22 Aug 2024 12:31:25 +0530 Subject: [PATCH 21/47] fix clippy --- .../programs/bridge-escrow/src/lib.rs | 15 ++++++++------- .../programs/bridge-escrow/src/tests.rs | 14 ++++---------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index dd5c8d2b..67ed051c 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -62,6 +62,7 @@ pub mod bridge_escrow { } /// Called by the auctioneer whose address is stored in `auctioneer` state account. + #[allow(clippy::too_many_arguments)] pub fn store_intent( ctx: Context, intent_id: String, @@ -139,6 +140,7 @@ pub mod bridge_escrow { } // this function is called by Solver + #[allow(unused_variables)] pub fn send_funds_to_user( ctx: Context, intent_id: String, @@ -179,8 +181,7 @@ pub mod bridge_escrow { // Transfer tokens from Auctioneer to Solver let bump = ctx.bumps.auctioneer_state; - let seeds = - &[AUCTIONEER_SEED.as_ref(), core::slice::from_ref(&bump)]; + let seeds = &[AUCTIONEER_SEED, core::slice::from_ref(&bump)]; let seeds = seeds.as_ref(); let signer_seeds = core::slice::from_ref(&seeds); @@ -254,27 +255,27 @@ pub mod bridge_escrow { .accounts .mint_authority .as_ref() - .and_then(|acc| Some(acc.to_account_info())), + .map(|acc| acc.to_account_info()), token_mint: ctx .accounts .token_mint .as_ref() - .and_then(|acc| Some(acc.to_account_info())), + .map(|acc| acc.to_account_info()), escrow_account: ctx .accounts .escrow_account .as_ref() - .and_then(|acc| Some(acc.to_account_info())), + .map(|acc| acc.to_account_info()), receiver_token_account: ctx .accounts .receiver_token_account .as_ref() - .and_then(|acc| Some(acc.to_account_info())), + .map(|acc| acc.to_account_info()), fee_collector: ctx .accounts .fee_collector .as_ref() - .and_then(|acc| Some(acc.to_account_info())), + .map(|acc| acc.to_account_info()), token_program: Some( ctx.accounts.token_program.to_account_info(), ), diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index 8c2aefd0..03ca02a1 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -1,25 +1,19 @@ use std::rc::Rc; -use std::str::FromStr; use std::thread::sleep; use std::time::Duration; use anchor_client::solana_client::rpc_client::RpcClient; use anchor_client::solana_client::rpc_config::RpcSendTransactionConfig; use anchor_client::solana_sdk::commitment_config::CommitmentConfig; -use anchor_client::solana_sdk::compute_budget::ComputeBudgetInstruction; use anchor_client::solana_sdk::pubkey::Pubkey; use anchor_client::solana_sdk::signature::{ read_keypair_file, Keypair, Signature, Signer as SolanaSigner, }; -use anchor_client::solana_sdk::system_transaction::transfer; use anchor_client::{Client, Cluster}; use anchor_lang::system_program; use anchor_spl::associated_token::{self, get_associated_token_address}; use anyhow::Result; -use ibc::apps::transfer::types::{PrefixedCoin, PrefixedDenom}; -use lib::hash::CryptoHash; use spl_token::instruction::initialize_mint2; -use spl_token::solana_program::native_token::LAMPORTS_PER_SOL; use spl_token::solana_program::system_instruction::create_account; const MINT_AMOUNT: u64 = 1_000_000_000; @@ -245,8 +239,8 @@ fn escrow_bridge_program() -> Result<()> { // Escrow user funds println!("Escrow user funds"); - let user_token_in_balance_before = - sol_rpc_client.get_token_account_balance(&user_token_in_addr).unwrap(); + // let user_token_in_balance_before = + // sol_rpc_client.get_token_account_balance(&user_token_in_addr).unwrap(); let sig = program .request() @@ -270,8 +264,8 @@ fn escrow_bridge_program() -> Result<()> { .unwrap(); println!(" Signature: {}", sig); - let user_token_in_balance_after = - sol_rpc_client.get_token_account_balance(&user_token_in_addr).unwrap(); + // let user_token_in_balance_after = + // sol_rpc_client.get_token_account_balance(&user_token_in_addr).unwrap(); // assert_eq!( // ((user_token_in_balance_after.ui_amount.unwrap() From b84d3ee5c7a687bfd373af2119e2457544ab213a Mon Sep 17 00:00:00 2001 From: dhruvja Date: Thu, 22 Aug 2024 12:36:37 +0530 Subject: [PATCH 22/47] fix clippy --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 67ed051c..2648efa4 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -31,6 +31,7 @@ mod tests; declare_id!("64K4AFty7UK9VJC6qykEVwFA93VoyND2uGyQgYa98ui9"); +#[allow(clippy::too_many_arguments)] #[program] pub mod bridge_escrow { use super::*; @@ -232,7 +233,7 @@ pub mod bridge_escrow { .accounts .receiver .as_ref() - .and_then(|acc| Some(acc.to_account_info())), + .map(|acc| acc.to_account_info()), storage: ctx .accounts .storage From 0a02300728f07787f1969f7a19c737139eaab2ed Mon Sep 17 00:00:00 2001 From: dhruvja Date: Thu, 22 Aug 2024 12:52:56 +0530 Subject: [PATCH 23/47] use struct for ix args instead of multiple args --- .../programs/bridge-escrow/src/lib.rs | 47 +++++++++++-------- .../programs/bridge-escrow/src/tests.rs | 38 ++++++++------- 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 2648efa4..d7313d92 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -31,7 +31,6 @@ mod tests; declare_id!("64K4AFty7UK9VJC6qykEVwFA93VoyND2uGyQgYa98ui9"); -#[allow(clippy::too_many_arguments)] #[program] pub mod bridge_escrow { use super::*; @@ -63,18 +62,9 @@ pub mod bridge_escrow { } /// Called by the auctioneer whose address is stored in `auctioneer` state account. - #[allow(clippy::too_many_arguments)] pub fn store_intent( ctx: Context, - intent_id: String, - user_in: Pubkey, - token_in: Pubkey, - amount_in: u64, - token_out: String, - amount_out: String, - timeout_in_sec: u64, - winner_solver: Pubkey, - single_domain: bool, + new_intent: IntentPayload, ) -> Result<()> { // verify if caller is auctioneer let auctioneer = &ctx.accounts.auctioneer; @@ -85,15 +75,19 @@ pub mod bridge_escrow { // save intent on a PDA derived from the auctioneer account let intent = &mut ctx.accounts.intent; - intent.intent_id = intent_id; - intent.user = user_in; - intent.token_in = token_in; - intent.amount_in = amount_in; - intent.token_out = token_out; - intent.timeout_timestamp_in_sec = timeout_in_sec; - intent.amount_out = amount_out; - intent.winner_solver = winner_solver; - intent.single_domain = single_domain; + + let current_timestamp = Clock::get()?.unix_timestamp as u64; + + intent.intent_id = new_intent.intent_id; + intent.user = new_intent.user_in; + intent.token_in = new_intent.token_in; + intent.amount_in = new_intent.amount_in; + intent.token_out = new_intent.token_out; + intent.timeout_timestamp_in_sec = new_intent.timeout_timestamp_in_sec; + intent.creation_timestamp_in_sec = current_timestamp; + intent.amount_out = new_intent.amount_out; + intent.winner_solver = new_intent.winner_solver; + intent.single_domain = new_intent.single_domain; Ok(()) } @@ -399,6 +393,19 @@ pub struct Intent { pub single_domain: bool, } +#[derive(AnchorSerialize, AnchorDeserialize, Debug)] +pub struct IntentPayload { + pub intent_id: String, + pub user_in: Pubkey, + pub token_in: Pubkey, + pub amount_in: u64, + pub token_out: String, + pub amount_out: String, + pub winner_solver: Pubkey, + pub timeout_timestamp_in_sec: u64, + pub single_domain: bool, +} + // Define the context for initializing the program #[derive(Accounts)] #[instruction()] diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index 03ca02a1..827c3ef0 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -16,6 +16,8 @@ use anyhow::Result; use spl_token::instruction::initialize_mint2; use spl_token::solana_program::system_instruction::create_account; +use crate::IntentPayload; + const MINT_AMOUNT: u64 = 1_000_000_000; const TRANSFER_AMOUNT: u64 = 1_000_000; @@ -288,6 +290,18 @@ fn escrow_bridge_program() -> Result<()> { ) .0; + let new_intent = IntentPayload { + intent_id: intent_id.clone(), + user_in: user.pubkey(), + token_in, + amount_in: TRANSFER_AMOUNT, + token_out: token_out.to_string(), + amount_out: amount_out.to_string(), + timeout_timestamp_in_sec: 10000, + winner_solver: solver.pubkey(), + single_domain: true, + }; + let sig = program .request() .accounts(crate::accounts::StoreIntent { @@ -296,17 +310,7 @@ fn escrow_bridge_program() -> Result<()> { auctioneer: auctioneer_state, system_program: anchor_lang::solana_program::system_program::ID, }) - .args(crate::instruction::StoreIntent { - intent_id: intent_id.clone(), - user_in: user.pubkey(), - token_in, - amount_in: TRANSFER_AMOUNT, - token_out: token_out.to_string(), - amount_out: amount_out.to_string(), - timeout_in_sec: 10000, - winner_solver: solver.pubkey(), - single_domain: true, - }) + .args(crate::instruction::StoreIntent { new_intent }) .payer(auctioneer.clone()) .signer(&*auctioneer) .send_with_spinner_and_config(RpcSendTransactionConfig { @@ -378,17 +382,17 @@ fn escrow_bridge_program() -> Result<()> { sol_rpc_client.get_token_account_balance(&user_token_out_addr).unwrap(); assert_eq!( - ((solver_token_in_balance_after.ui_amount.unwrap() - - solver_token_in_balance_before.ui_amount.unwrap()) * - 1_000_000f64) + ((solver_token_in_balance_after.ui_amount.unwrap() + - solver_token_in_balance_before.ui_amount.unwrap()) + * 1_000_000f64) .round() as u64, TRANSFER_AMOUNT ); assert_eq!( - ((user_token_out_balance_after.ui_amount.unwrap() - - user_token_out_balance_before.ui_amount.unwrap()) * - 1_000_000f64) + ((user_token_out_balance_after.ui_amount.unwrap() + - user_token_out_balance_before.ui_amount.unwrap()) + * 1_000_000f64) .round() as u64, amount_out ); From 777c22ace15c4fdc1b91f340f3ac66d744ca331a Mon Sep 17 00:00:00 2001 From: dhruvja Date: Thu, 22 Aug 2024 12:58:11 +0530 Subject: [PATCH 24/47] fmt --- .../programs/bridge-escrow/src/tests.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index 827c3ef0..91df7591 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -382,17 +382,17 @@ fn escrow_bridge_program() -> Result<()> { sol_rpc_client.get_token_account_balance(&user_token_out_addr).unwrap(); assert_eq!( - ((solver_token_in_balance_after.ui_amount.unwrap() - - solver_token_in_balance_before.ui_amount.unwrap()) - * 1_000_000f64) + ((solver_token_in_balance_after.ui_amount.unwrap() - + solver_token_in_balance_before.ui_amount.unwrap()) * + 1_000_000f64) .round() as u64, TRANSFER_AMOUNT ); assert_eq!( - ((user_token_out_balance_after.ui_amount.unwrap() - - user_token_out_balance_before.ui_amount.unwrap()) - * 1_000_000f64) + ((user_token_out_balance_after.ui_amount.unwrap() - + user_token_out_balance_before.ui_amount.unwrap()) * + 1_000_000f64) .round() as u64, amount_out ); From 5e86bc104ca2e02fa870579609a11b29b7bbb474 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Thu, 22 Aug 2024 15:51:25 +0530 Subject: [PATCH 25/47] fix wallet path --- Anchor.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Anchor.toml b/Anchor.toml index 0b183634..256a1ad1 100644 --- a/Anchor.toml +++ b/Anchor.toml @@ -19,7 +19,7 @@ url = "https://api.apr.dev" [provider] cluster = "Localnet" -wallet = "/Users/dhruvjain/.config/solana/id.json" +wallet = "~/.config/solana/id.json" [workspace] members = ["solana/bridge-escrow/programs/bridge-escrow", "solana/restaking/programs/restaking", "solana/solana-ibc/programs/solana-ibc"] From c0e7f13035724e159dd2cb3441182b297a45ed45 Mon Sep 17 00:00:00 2001 From: Dhruv D Jain Date: Mon, 26 Aug 2024 18:34:35 +0100 Subject: [PATCH 26/47] fast-bridge: Send required accounts for cross domain transfer (#375) For cross domain transfers, an acknowledgement is sent from destination to source in form of a token transfer. The packet contains the memo that has the information about unlocking the funds. The source would then parse the memo and unlock the funds to the solver mentioned in the memo. Since we only have token transfers enabled and no cross chain messages, a token needs to be transferred. For this, we create a dummy token owned by the program which mints a token everytime and sends a transfer. The timeout of the transfer is set to infinite so that it always reaches the counterparty chain. Also the `on_receive_transfer` method accepts a memo which unlocks the funds to the solver. Right now it is being called by the auctioneer but once the hooks are enabled on `solana-ibc` program, this method would then be called by the `solana-ibc` program. --- solana-test.sh | 22 +- .../programs/bridge-escrow/src/lib.rs | 209 +++++++++++----- .../programs/bridge-escrow/src/tests.rs | 231 ++++++++++-------- 3 files changed, 287 insertions(+), 175 deletions(-) diff --git a/solana-test.sh b/solana-test.sh index 3f33b9f4..525045f2 100755 --- a/solana-test.sh +++ b/solana-test.sh @@ -1,15 +1,15 @@ #!/bin/sh -# set -eux -# solana config set --url http://127.0.0.1:8899 -# cd solana/write-account -# cargo build-sbf -# cd ../.. -# cd solana/signature-verifier -# cargo build-sbf -# cd ../.. -# solana program deploy target/deploy/write.so -# solana program deploy target/deploy/sigverify.so -# cargo test --lib -- --nocapture --include-ignored ::anchor +set -eux +solana config set --url http://127.0.0.1:8899 +cd solana/write-account +cargo build-sbf +cd ../.. +cd solana/signature-verifier +cargo build-sbf +cd ../.. +solana program deploy target/deploy/write.so +solana program deploy target/deploy/sigverify.so +cargo test --lib -- --nocapture --include-ignored ::anchor cargo test --lib -- --nocapture --include-ignored ::escrow # find solana/restaking/tests/ -name '*.ts' \ # -exec yarn run ts-mocha -p ./tsconfig.json -t 1000000 {} + diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index d7313d92..0e44d7f8 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -8,8 +8,6 @@ use anchor_spl::token::{Mint, Token, TokenAccount, Transfer as SplTransfer}; use ibc::apps::transfer::types::msgs::transfer::MsgTransfer; use ibc::apps::transfer::types::packet::PacketData; use ibc::apps::transfer::types::{PrefixedCoin, PrefixedDenom}; -use ibc::core::channel::types::timeout::TimeoutHeight::At; -use ibc::core::client::types::Height; use ibc::core::host::types::identifiers::{ChannelId, PortId}; use ibc::core::primitives::Timestamp; use ibc::primitives::Signer as IbcSigner; @@ -20,11 +18,14 @@ use solana_ibc::cpi::send_transfer; use solana_ibc::program::SolanaIbc; use solana_ibc::storage::PrivateStorage; -const DUMMY: &str = "0x36dd1bfe89d409f869fabbe72c3cf72ea8b460f6"; +// const DUMMY: &str = "0x36dd1bfe89d409f869fabbe72c3cf72ea8b460f6"; // const BRIDGE_CONTRACT_PUBKEY: &str = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"; const AUCTIONEER_SEED: &[u8] = b"auctioneer"; const INTENT_SEED: &[u8] = b"intent"; +const DUMMY_SEED: &[u8] = b"dummy"; + +const DUMMY_TOKEN_TRANSFER_AMOUNT: u64 = 1; #[cfg(test)] mod tests; @@ -33,8 +34,14 @@ declare_id!("64K4AFty7UK9VJC6qykEVwFA93VoyND2uGyQgYa98ui9"); #[program] pub mod bridge_escrow { + use anchor_spl::token::{CloseAccount, MintTo}; + use ibc::core::channel::types::timeout::TimeoutHeight; + use super::*; + /// Sets the authority and creates a token mint which would be used to + /// send acknowledgements to the counterparty chain. The token doesnt have + /// any value is just used to transfer messages. pub fn initialize(ctx: Context) -> Result<()> { // store the auctioneer let auctioneer = &mut ctx.accounts.auctioneer; @@ -78,6 +85,11 @@ pub mod bridge_escrow { let current_timestamp = Clock::get()?.unix_timestamp as u64; + require!( + current_timestamp < new_intent.timeout_timestamp_in_sec, + ErrorCode::InvalidTimeout + ); + intent.intent_id = new_intent.intent_id; intent.user = new_intent.user_in; intent.token_in = new_intent.token_in; @@ -92,42 +104,59 @@ pub mod bridge_escrow { Ok(()) } - // ONLY bridge contract should call this function - /* - I assume this need to be done outside the Program to get the accounts - - // Extract and validate the memo - let memo = msg.packet_data.memo.to_string(); - let parts: Vec<&str> = memo.split(',').collect(); - let (token_mint, amount, solver) = (parts[0], parts[1], parts[2]); - - ctx.accounts.auctioneer = get_token_account(token_mint, auctioneer); - ctx.accounts.solver = get_token_account(token_mint, solver); - */ + /// The memo should contain the token mint address, amount and solver address + /// seperated by commas. Right now this method can only be called by the + /// auctioneer. + /// + /// TODO: Modify the method such that the method can only be called by + /// the solana-ibc bridge contract. This would then remove the trust factor + /// from the auctioneer. pub fn on_receive_transfer( ctx: Context, - msg: MsgTransfer, + memo: String, ) -> Result<()> { // Extract and validate the memo - let memo = msg.packet_data.memo.to_string(); let parts: Vec<&str> = memo.split(',').collect(); - require!( - msg.packet_data.token.denom.base_denom.to_string() == DUMMY, - ErrorCode::InvalidDenom - ); + // require!( + // msg.packet_data.token.denom.base_denom.to_string() == DUMMY, + // ErrorCode::InvalidDenom + // ); + let token_mint = + Pubkey::from_str(parts[0]).map_err(|_| ErrorCode::BadPublickey)?; let amount: u64 = parts[1].parse().map_err(|_| ErrorCode::InvalidAmount)?; + let solver = + Pubkey::from_str(parts[2]).map_err(|_| ErrorCode::BadPublickey)?; + + if token_mint != ctx.accounts.token_mint.key() { + return Err(ErrorCode::InvalidTokenAddress.into()); + } + + if solver != ctx.accounts.solver_token_account.owner { + return Err(ErrorCode::InvalidSolverOutAddress.into()); + } // Transfer tokens from Auctioneer to Solver let cpi_accounts = SplTransfer { - from: ctx.accounts.auctioneer.to_account_info(), - to: ctx.accounts.solver.to_account_info(), - authority: ctx.accounts.auctioneer.to_account_info(), + from: ctx.accounts.escrow_token_account.to_account_info(), + to: ctx.accounts.solver_token_account.to_account_info(), + authority: ctx.accounts.auctioneer_state.to_account_info(), }; + let seeds = &[ + AUCTIONEER_SEED, + core::slice::from_ref(&ctx.bumps.auctioneer_state), + ]; + let seeds = seeds.as_ref(); + let signer_seeds = core::slice::from_ref(&seeds); + let cpi_program = ctx.accounts.token_program.to_account_info(); - let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts); + let cpi_ctx = CpiContext::new_with_signer( + cpi_program, + cpi_accounts, + signer_seeds, + ); token::transfer(cpi_ctx, amount)?; @@ -172,20 +201,27 @@ pub mod bridge_escrow { amount_out, )?; + let bump = ctx.bumps.auctioneer_state; + let seeds = &[AUCTIONEER_SEED, core::slice::from_ref(&bump)]; + let seeds = seeds.as_ref(); + let signer_seeds = core::slice::from_ref(&seeds); + if intent.single_domain { // Transfer tokens from Auctioneer to Solver - - let bump = ctx.bumps.auctioneer_state; - let seeds = &[AUCTIONEER_SEED, core::slice::from_ref(&bump)]; - let seeds = seeds.as_ref(); - let signer_seeds = core::slice::from_ref(&seeds); + let auctioneer_token_in_account = ctx + .accounts + .auctioneer_token_in_account + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)?; + let solver_token_in_account = ctx + .accounts + .solver_token_in_account + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)?; let cpi_accounts = SplTransfer { - from: ctx - .accounts - .auctioneer_token_in_account - .to_account_info(), - to: ctx.accounts.solver_token_in_account.to_account_info(), + from: auctioneer_token_in_account.to_account_info(), + to: solver_token_in_account.to_account_info(), authority: ctx.accounts.auctioneer_state.to_account_info(), }; let cpi_program = token_program.to_account_info(); @@ -214,15 +250,36 @@ pub mod bridge_escrow { intent.token_out, intent.amount_out, solver_out ); + let receiver_token_account = ctx + .accounts + .receiver_token_account + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)?; + + // Mint dummy tokens so that they can transferred + let mint_acc = MintTo { + mint: token_mint.to_account_info(), + to: receiver_token_account.to_account_info(), + authority: ctx.accounts.auctioneer_state.to_account_info(), + }; + + let cpi_ctx = CpiContext::new_with_signer( + ctx.accounts.token_program.to_account_info(), + mint_acc, + signer_seeds, + ); + + anchor_spl::token::mint_to(cpi_ctx, DUMMY_TOKEN_TRANSFER_AMOUNT)?; + // Cross-chain transfer + memo - let transfer_ctx = CpiContext::new( + let transfer_ctx = CpiContext::new_with_signer( ctx.accounts .ibc_program .as_ref() .ok_or(ErrorCode::AccountsNotPresent)? .to_account_info(), SendTransfer { - sender: solver.to_account_info(), + sender: ctx.accounts.solver.to_account_info(), receiver: ctx .accounts .receiver @@ -261,11 +318,9 @@ pub mod bridge_escrow { .escrow_account .as_ref() .map(|acc| acc.to_account_info()), - receiver_token_account: ctx - .accounts - .receiver_token_account - .as_ref() - .map(|acc| acc.to_account_info()), + receiver_token_account: Some( + receiver_token_account.to_account_info(), + ), fee_collector: ctx .accounts .fee_collector @@ -279,6 +334,7 @@ pub mod bridge_escrow { .system_program .to_account_info(), }, + signer_seeds, ); let memo = "{\"forward\":{\"receiver\":\"\ @@ -299,7 +355,7 @@ pub mod bridge_escrow { &token_mint.key().to_string(), ) .unwrap(), // token only owned by this PDA - amount: 1.into(), + amount: DUMMY_TOKEN_TRANSFER_AMOUNT.into(), }, sender: IbcSigner::from( ctx.accounts.solver.key().to_string(), @@ -307,28 +363,35 @@ pub mod bridge_escrow { receiver: String::from("pfm").into(), memo: memo.into(), }, - timeout_height_on_b: At( - Height::new(2018502000, 29340670).unwrap() - ), - timeout_timestamp_on_b: Timestamp::from_nanoseconds( - 1000000000000000000, - ) - .unwrap(), + timeout_height_on_b: TimeoutHeight::Never, + timeout_timestamp_on_b: Timestamp::from_nanoseconds(u64::MAX) + .unwrap(), }; send_transfer(transfer_ctx, hashed_full_denom, msg)?; - } - // // Delete intent by closing the account - // let intent_account_info = &mut ctx.accounts.intent.to_account_info(); - // **intent_account_info.try_borrow_mut_lamports()? = 0; - // intent_account_info.data.borrow_mut().fill(0); + // Close the dummy token account. + let close_accs = CloseAccount { + account: receiver_token_account.to_account_info(), + destination: ctx.accounts.solver.to_account_info(), + authority: ctx.accounts.solver.to_account_info(), + }; + + let cpi_ctx = CpiContext::new( + ctx.accounts.token_program.to_account_info(), + close_accs, + ); + anchor_spl::token::close_account(cpi_ctx)?; + } Ok(()) } /// If the intent has not been solved, then the funds can withdrawn by the user /// after the timeout period has passed. + /// + /// TODO: The funds should only be withdrawn if the message is sent through IBC that + /// the request got timed out. pub fn on_timeout( ctx: Context, _intent_id: String, @@ -414,7 +477,13 @@ pub struct Initialize<'info> { pub authority: Signer<'info>, #[account(init, seeds = [AUCTIONEER_SEED], bump, payer = authority, space = 8 + 32)] pub auctioneer: Account<'info, Auctioneer>, + + #[account(init, payer = authority, seeds = [DUMMY_SEED], bump, mint::decimals = 9, mint::authority = auctioneer)] + pub token_mint: Account<'info, Mint>, + pub system_program: Program<'info, System>, + pub token_program: Program<'info, Token>, + pub associated_token_program: Program<'info, AssociatedToken>, } // Define the context for storing intent @@ -434,20 +503,24 @@ pub struct StoreIntent<'info> { #[instruction(intent_id: String)] pub struct ReceiveTransferContext<'info> { #[account(mut)] - pub solver: Signer<'info>, - #[account(seeds = [AUCTIONEER_SEED], bump)] + pub authority: Signer<'info>, + + #[account(seeds = [AUCTIONEER_SEED], bump, has_one = authority)] pub auctioneer_state: Account<'info, Auctioneer>, - /// CHECK: - pub auctioneer: UncheckedAccount<'info>, - #[account(mut, close = auctioneer, seeds = [INTENT_SEED, intent_id.as_bytes()], bump)] + #[account(mut, close = authority, seeds = [INTENT_SEED, intent_id.as_bytes()], bump)] pub intent: Account<'info, Intent>, + + pub token_mint: Account<'info, Mint>, + #[account(mut, token::mint = token_mint, token::authority = auctioneer_state)] + pub escrow_token_account: Account<'info, TokenAccount>, + #[account(mut, token::mint = token_mint)] + pub solver_token_account: Account<'info, TokenAccount>, + #[account(address = solana_program::sysvar::instructions::ID)] /// CHECK: Used for getting the caller program id to verify if the right /// program is calling the method. pub instruction: UncheckedAccount<'info>, pub token_program: Program<'info, Token>, - #[account(mut)] - pub token_account: Account<'info, TokenAccount>, } // Accounts for transferring SPL tokens @@ -466,14 +539,14 @@ pub struct SplTokenTransfer<'info> { /// CHECK: pub auctioneer: UncheckedAccount<'info>, - pub token_in: Account<'info, Mint>, + pub token_in: Option>, pub token_out: Account<'info, Mint>, // Program (Escrow) -> Solver SPL Token Transfer Accounts #[account(mut, token::mint = token_in, token::authority = auctioneer_state)] - pub auctioneer_token_in_account: Account<'info, TokenAccount>, + pub auctioneer_token_in_account: Option>, #[account(mut, token::authority = solver, token::mint = token_in)] - pub solver_token_in_account: Account<'info, TokenAccount>, + pub solver_token_in_account: Option>, // Solver -> User SPL Token Transfer Accounts #[account(mut, token::authority = solver, token::mint = token_out)] @@ -502,12 +575,12 @@ pub struct SplTokenTransfer<'info> { /// CHECK: #[account(mut)] pub mint_authority: Option>, - #[account(mut)] + #[account(mut, seeds = [DUMMY_SEED], bump)] pub token_mint: Option>>, /// CHECK: #[account(mut)] pub escrow_account: Option>, - #[account(mut)] + #[account(init_if_needed, payer = solver, associated_token::mint = token_mint, associated_token::authority = solver)] pub receiver_token_account: Option>>, /// CHECK: #[account(mut)] @@ -578,4 +651,6 @@ pub enum ErrorCode { InvalidSolverOutAddress, #[msg("Invalid hashed full denom")] InvalidHashedFullDenom, + #[msg("Unable to parse public key from string")] + BadPublickey, } diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index 91df7591..6f5592a3 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -1,10 +1,11 @@ use std::rc::Rc; use std::thread::sleep; -use std::time::Duration; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; use anchor_client::solana_client::rpc_client::RpcClient; use anchor_client::solana_client::rpc_config::RpcSendTransactionConfig; use anchor_client::solana_sdk::commitment_config::CommitmentConfig; +use anchor_client::solana_sdk::compute_budget::ComputeBudgetInstruction; use anchor_client::solana_sdk::pubkey::Pubkey; use anchor_client::solana_sdk::signature::{ read_keypair_file, Keypair, Signature, Signer as SolanaSigner, @@ -197,24 +198,8 @@ fn escrow_bridge_program() -> Result<()> { println!(" Signature: {}", tx); - // let hashed_full_denom = lib::hash::CryptoHash::digest( - // &native_token_mint_key.to_string().as_bytes(), - // ); - - // println!("Native token mint {}", native_token_mint_key); - // println!("hashed full denom {}", hashed_full_denom); - - // let x = PrefixedCoin { - // denom: PrefixedDenom::from_str(&native_token_mint_key.to_string()) - // .unwrap(), // token only owned by this PDA - // amount: 1.into(), - // }; - - // println!("full denom {:?}", x.denom.to_string()); - // println!( - // "hashed full denom {:?}", - // lib::hash::CryptoHash::digest(x.denom.to_string().as_bytes()) - // ); + let dummy_token_mint = + Pubkey::find_program_address(&[crate::DUMMY_SEED], &crate::ID).0; // Initialize the progroam to define the auctioneer println!("\nInitializing the program"); @@ -223,7 +208,10 @@ fn escrow_bridge_program() -> Result<()> { .accounts(crate::accounts::Initialize { authority: auctioneer.pubkey(), auctioneer: auctioneer_state, + token_mint: dummy_token_mint, system_program: anchor_lang::solana_program::system_program::ID, + token_program: anchor_spl::token::ID, + associated_token_program: anchor_spl::associated_token::ID, }) .args(crate::instruction::Initialize {}) .payer(auctioneer.clone()) @@ -239,7 +227,7 @@ fn escrow_bridge_program() -> Result<()> { get_associated_token_address(&auctioneer_state, &token_in); // Escrow user funds - println!("Escrow user funds"); + println!("\nEscrow user funds for single domain"); // let user_token_in_balance_before = // sol_rpc_client.get_token_account_balance(&user_token_in_addr).unwrap(); @@ -278,7 +266,7 @@ fn escrow_bridge_program() -> Result<()> { // ); // Store the intent - println!("Store the intent"); + println!("\nStore the intent for single domain"); let intent_id = "12323542".to_string(); // arbitrary value @@ -290,6 +278,9 @@ fn escrow_bridge_program() -> Result<()> { ) .0; + let current_timestamp = + SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); + let new_intent = IntentPayload { intent_id: intent_id.clone(), user_in: user.pubkey(), @@ -297,7 +288,7 @@ fn escrow_bridge_program() -> Result<()> { amount_in: TRANSFER_AMOUNT, token_out: token_out.to_string(), amount_out: amount_out.to_string(), - timeout_timestamp_in_sec: 10000, + timeout_timestamp_in_sec: current_timestamp + 10000, winner_solver: solver.pubkey(), single_domain: true, }; @@ -321,7 +312,7 @@ fn escrow_bridge_program() -> Result<()> { println!(" Signature: {}", sig); // Send funds to user ( single domain ) - println!("Send funds to user single domain"); + println!("\nSend funds to user single domain"); let solver_token_in_addr = get_associated_token_address(&solver.pubkey(), &token_in); @@ -341,10 +332,10 @@ fn escrow_bridge_program() -> Result<()> { intent: intent_state, auctioneer_state, auctioneer: auctioneer.pubkey(), - token_in, + token_in: Some(token_in), token_out, - auctioneer_token_in_account: token_in_escrow_addr, - solver_token_in_account: solver_token_in_addr, + auctioneer_token_in_account: Some(token_in_escrow_addr), + solver_token_in_account: Some(solver_token_in_addr), solver_token_out_account: solver_token_out_addr, user_token_out_account: user_token_out_addr, token_program: anchor_spl::token::ID, @@ -397,82 +388,128 @@ fn escrow_bridge_program() -> Result<()> { amount_out ); - // If above fails -> timeout + // Store the intent + println!("\nStore the intent for cross domain"); + let intent_id = "12323543".to_string(); - // // Derive the necessary accounts - // let (storage, _bump_storage) = Pubkey::find_program_address( - // &[solana_ibc::SOLANA_IBC_STORAGE_SEED], - // &solana_ibc::ID, - // ); - // let (trie, _bump_trie) = - // Pubkey::find_program_address(&[solana_ibc::TRIE_SEED], &solana_ibc::ID); - // let (chain, _bump_chain) = Pubkey::find_program_address( - // &[solana_ibc::CHAIN_SEED], - // &solana_ibc::ID, - // ); - // let (mint_authority, _bump_mint_authority) = Pubkey::find_program_address( - // &[solana_ibc::MINT_ESCROW_SEED], - // &solana_ibc::ID, - // ); - // let (escrow_account, _bump_escrow_account) = Pubkey::find_program_address( - // &[solana_ibc::ESCROW, &hashed_full_denom.as_slice()], - // &solana_ibc::ID, - // ); + // arbitrary value + let amount_out = 10000; - // let receiver_token_account = get_associated_token_address( - // &authority.pubkey(), - // &native_token_mint_key, - // ); - // let (fee_collector, _bump_fee_collector) = - // Pubkey::find_program_address(&[solana_ibc::FEE_SEED], &solana_ibc::ID); + let intent_state = Pubkey::find_program_address( + &[crate::INTENT_SEED, intent_id.as_bytes()], + &crate::ID, + ) + .0; + + let new_intent = IntentPayload { + intent_id: intent_id.clone(), + user_in: user.pubkey(), + token_in, + amount_in: TRANSFER_AMOUNT, + token_out: token_out.to_string(), + amount_out: amount_out.to_string(), + timeout_timestamp_in_sec: current_timestamp + 10000, + winner_solver: solver.pubkey(), + single_domain: false, + }; + + let sig = program + .request() + .accounts(crate::accounts::StoreIntent { + authority: auctioneer.pubkey(), + intent: intent_state, + auctioneer: auctioneer_state, + system_program: anchor_lang::solana_program::system_program::ID, + }) + .args(crate::instruction::StoreIntent { new_intent }) + .payer(auctioneer.clone()) + .signer(&*auctioneer) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }) + .unwrap(); + println!(" Signature: {}", sig); - // let system_program = anchor_lang::system_program::ID; + // Send funds to user ( cross domain ) + println!("\nSend funds to user cross domain"); - // // Amount to transfer - // let amount = 1000000; // Example amount + let hashed_full_denom = + lib::hash::CryptoHash::digest(&dummy_token_mint.to_string().as_bytes()); - // let destination_token_account = get_associated_token_address( - // &receiver.pubkey(), - // &native_token_mint_key, - // ); + println!("\nNative token mint {}", dummy_token_mint); + println!("hashed full denom {}", hashed_full_denom); - // // Build and send the transaction to call send_funds_to_user - // println!("\nSending funds to user"); - // let sig = program - // .request() - // .instruction(ComputeBudgetInstruction::set_compute_unit_limit( - // 1_000_000, - // )) - // .accounts(crate::accounts::SplTokenTransfer { - // authority: authority.pubkey(), - // solver_token_in_account: receiver_token_account, - // user_token_in_account, - // ibc_program: solana_ibc::ID, - // receiver: receiver.pubkey(), - // storage, - // trie, - // chain, - // mint_authority, - // token_mint: native_token_mint_key, - // escrow_account, - // receiver_token_account, - // fee_collector, - // token_program: anchor_spl::token::ID, - // associated_token_program: anchor_spl::associated_token::ID, - // system_program, - // intent: todo!(), - // auctioneer: todo!(), - // auctioneer_token_in_account: todo!(), - // solver_token_out_account: todo!(), - // auctioneer_token_out_account: todo!(), - // }) - // .args(crate::instruction::SendFundsToUser { amount, hashed_full_denom }) - // .payer(authority.clone()) - // .signer(&*authority) - // .send_with_spinner_and_config(RpcSendTransactionConfig { - // skip_preflight: true, - // ..RpcSendTransactionConfig::default() - // })?; - // println!(" Signature: {sig}"); + // Derive the necessary accounts + let (storage, _bump_storage) = Pubkey::find_program_address( + &[solana_ibc::SOLANA_IBC_STORAGE_SEED], + &solana_ibc::ID, + ); + let (trie, _bump_trie) = + Pubkey::find_program_address(&[solana_ibc::TRIE_SEED], &solana_ibc::ID); + let (chain, _bump_chain) = Pubkey::find_program_address( + &[solana_ibc::CHAIN_SEED], + &solana_ibc::ID, + ); + let (mint_authority, _bump_mint_authority) = Pubkey::find_program_address( + &[solana_ibc::MINT_ESCROW_SEED], + &solana_ibc::ID, + ); + let (escrow_account, _bump_escrow_account) = Pubkey::find_program_address( + &[solana_ibc::ESCROW, &hashed_full_denom.as_slice()], + &solana_ibc::ID, + ); + + let (fee_collector, _bump_fee_collector) = + Pubkey::find_program_address(&[solana_ibc::FEE_SEED], &solana_ibc::ID); + + let receiver_token_account = + get_associated_token_address(&solver.pubkey(), &dummy_token_mint); + + // Build and send the transaction to call send_funds_to_user + println!("\nSending funds to user"); + let sig = program + .request() + .instruction(ComputeBudgetInstruction::set_compute_unit_limit( + 1_000_000, + )) + .accounts(crate::accounts::SplTokenTransfer { + intent: intent_state, + auctioneer_state, + solver: solver.pubkey(), + auctioneer: auctioneer.pubkey(), + token_in: None, + token_out, + auctioneer_token_in_account: None, + solver_token_in_account: None, + solver_token_out_account: solver_token_out_addr, + user_token_out_account: user_token_out_addr, + token_program: anchor_spl::token::ID, + associated_token_program: anchor_spl::associated_token::ID, + system_program: anchor_lang::solana_program::system_program::ID, + ibc_program: Some(solana_ibc::ID), + receiver: None, + storage: Some(storage), + trie: Some(trie), + chain: Some(chain), + mint_authority: Some(mint_authority), + token_mint: Some(dummy_token_mint), + escrow_account: Some(escrow_account), + receiver_token_account: Some(receiver_token_account), + fee_collector: Some(fee_collector), + }) + .args(crate::instruction::SendFundsToUser { + intent_id, + hashed_full_denom: Some(hashed_full_denom), + // Solver out doesnt matter for this test + solver_out: Some(Pubkey::new_unique().to_string()), + }) + .payer(solver.clone()) + .signer(&*solver) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..RpcSendTransactionConfig::default() + })?; + println!(" Signature: {sig}"); Ok(()) } From 15a4ad7e0bf197ca3f95e7a625e61d3872692dcb Mon Sep 17 00:00:00 2001 From: Dhruv D Jain Date: Mon, 26 Aug 2024 18:43:14 +0100 Subject: [PATCH 27/47] fast-bridge: Emit events for each method. (#374) Emitting events for all instructions so that they can be parsed from the logs and be acted upon. --- .../programs/bridge-escrow/src/events.rs | 119 ++++++++++++++++++ .../programs/bridge-escrow/src/lib.rs | 99 ++++++++++++++- 2 files changed, 212 insertions(+), 6 deletions(-) create mode 100644 solana/bridge-escrow/programs/bridge-escrow/src/events.rs diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/events.rs b/solana/bridge-escrow/programs/bridge-escrow/src/events.rs new file mode 100644 index 00000000..f0213003 --- /dev/null +++ b/solana/bridge-escrow/programs/bridge-escrow/src/events.rs @@ -0,0 +1,119 @@ +use anchor_lang::prelude::borsh; +use anchor_lang::solana_program::log; +use anchor_lang::solana_program::pubkey::Pubkey; + +use crate::Intent; + +/// Events that can be emitted by the program. +/// +/// The events are logged in their borsh-serialised form. +/// +/// The events names are similar to the function names that emit them +/// to remain the consistency. +#[derive( + Clone, + Debug, + PartialEq, + Eq, + borsh::BorshSerialize, + borsh::BorshDeserialize, + derive_more::From, +)] + +pub enum Event { + EscrowFunds(EscrowFunds), + StoreIntent(StoreIntent), + OnReceiveTransfer(OnReceiveTransfer), + SendFundsToUser(SendFundsToUser), + OnTimeout(OnTimeout), +} + +#[derive( + Clone, + Debug, + PartialEq, + Eq, + borsh::BorshSerialize, + borsh::BorshDeserialize, + derive_more::From, +)] +pub struct EscrowFunds { + pub amount: u64, + pub sender: Pubkey, + pub token_mint: Pubkey, +} + +#[derive( + Clone, + Debug, + PartialEq, + Eq, + borsh::BorshSerialize, + borsh::BorshDeserialize, + derive_more::From, +)] +pub struct StoreIntent { + pub intent: Intent, +} + +#[derive( + Clone, + Debug, + PartialEq, + Eq, + borsh::BorshSerialize, + borsh::BorshDeserialize, + derive_more::From, +)] +pub struct OnReceiveTransfer { + pub amount: u64, + pub solver: Pubkey, +} + +#[derive( + Clone, + Debug, + PartialEq, + Eq, + borsh::BorshSerialize, + borsh::BorshDeserialize, + derive_more::From, +)] +pub struct SendFundsToUser { + pub amount: u64, + pub receiver: Pubkey, + pub token_mint: Pubkey, + pub intent_id: String, + /// The solver on source chain who would receive + /// the escrowed amount when the intent is acknowledged. + /// + /// Would be `None` in case of single domain transfer. + pub solver_out: Option, +} + +#[derive( + Clone, + Debug, + PartialEq, + Eq, + borsh::BorshSerialize, + borsh::BorshDeserialize, + derive_more::From, +)] +pub struct OnTimeout { + pub amount: u64, + pub token_mint: Pubkey, + pub intent_id: String, +} + +impl Event { + pub fn emit(&self) -> Result<(), String> { + borsh::BorshSerialize::try_to_vec(self) + .map(|data| log::sol_log_data(&[data.as_slice()])) + .map_err(|err| err.to_string()) + } +} + +pub fn emit(event: impl Into) -> Result<(), String> { + event.into().emit() +} diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 0e44d7f8..faeea579 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -27,6 +27,7 @@ const DUMMY_SEED: &[u8] = b"dummy"; const DUMMY_TOKEN_TRANSFER_AMOUNT: u64 = 1; +pub mod events; #[cfg(test)] mod tests; @@ -51,7 +52,13 @@ pub mod bridge_escrow { /// Escrows the user funds on the source chain /// - /// The funds are stored in token account owned by the auctioneer state PDA + /// The funds are stored in token account owned by the auctioneer state PDA. Right now + /// all the deposits are present in a single pool. But we would want to deposit the funds + /// in seperate account so that we dont touch the funds of other users. + /// + /// TODO: Store the intent without `amount_out` and `solver_out` which would then be + /// updated by auctioneer. Also escrow the funds in an account whose seeds are the + /// intent id. pub fn escrow_funds(ctx: Context, amount: u64) -> Result<()> { // Transfer SPL tokens from the user's account to the auctioneer's account let cpi_accounts = SplTransfer { @@ -65,6 +72,16 @@ pub mod bridge_escrow { token::transfer(cpi_ctx, amount)?; + events::emit(events::Event::EscrowFunds(events::EscrowFunds { + amount, + sender: ctx.accounts.user.key(), + token_mint: ctx.accounts.token_mint.key(), + })) + .map_err(|err| { + msg!("{}", err); + ErrorCode::InvalidEventFormat + })?; + Ok(()) } @@ -90,17 +107,36 @@ pub mod bridge_escrow { ErrorCode::InvalidTimeout ); - intent.intent_id = new_intent.intent_id; + intent.intent_id = new_intent.intent_id.clone(); intent.user = new_intent.user_in; intent.token_in = new_intent.token_in; intent.amount_in = new_intent.amount_in; - intent.token_out = new_intent.token_out; + intent.token_out = new_intent.token_out.clone(); intent.timeout_timestamp_in_sec = new_intent.timeout_timestamp_in_sec; intent.creation_timestamp_in_sec = current_timestamp; - intent.amount_out = new_intent.amount_out; + intent.amount_out = new_intent.amount_out.clone(); intent.winner_solver = new_intent.winner_solver; intent.single_domain = new_intent.single_domain; + events::emit(events::Event::StoreIntent(events::StoreIntent { + intent: Intent { + intent_id: new_intent.intent_id, + user: new_intent.user_in, + token_in: new_intent.token_in, + amount_in: new_intent.amount_in, + token_out: new_intent.token_out, + amount_out: new_intent.amount_out, + winner_solver: new_intent.winner_solver, + creation_timestamp_in_sec: current_timestamp, + timeout_timestamp_in_sec: new_intent.timeout_timestamp_in_sec, + single_domain: new_intent.single_domain, + }, + })) + .map_err(|err| { + msg!("{}", err); + ErrorCode::InvalidEventFormat + })?; + Ok(()) } @@ -160,6 +196,17 @@ pub mod bridge_escrow { token::transfer(cpi_ctx, amount)?; + events::emit(events::Event::OnReceiveTransfer( + events::OnReceiveTransfer { + amount, + solver: ctx.accounts.solver_token_account.owner, + }, + )) + .map_err(|err| { + msg!("{}", err); + ErrorCode::InvalidEventFormat + })?; + Ok(()) } @@ -233,6 +280,20 @@ pub mod bridge_escrow { ), intent.amount_in, )?; + + events::emit(events::Event::SendFundsToUser( + events::SendFundsToUser { + amount: amount_out, + receiver: intent.user, + token_mint: ctx.accounts.token_out.key(), + intent_id, + solver_out, + }, + )) + .map_err(|err| { + msg!("{}", err); + ErrorCode::InvalidEventFormat + })?; } else { let solver_out = solver_out.ok_or(ErrorCode::InvalidSolverAddress)?; @@ -383,7 +444,21 @@ pub mod bridge_escrow { ); anchor_spl::token::close_account(cpi_ctx)?; + events::emit(events::Event::SendFundsToUser( + events::SendFundsToUser { + amount: amount_out, + receiver: intent.user, + token_mint: ctx.accounts.token_out.key(), + intent_id, + solver_out: Some(solver_out), + }, + )) + .map_err(|err| { + msg!("{}", err); + ErrorCode::InvalidEventFormat + })?; } + Ok(()) } @@ -394,7 +469,7 @@ pub mod bridge_escrow { /// the request got timed out. pub fn on_timeout( ctx: Context, - _intent_id: String, + intent_id: String, ) -> Result<()> { let authority = &ctx.accounts.user.key(); @@ -426,6 +501,16 @@ pub mod bridge_escrow { ); anchor_spl::token::transfer(cpi_ctx, intent.amount_in)?; + events::emit(events::Event::OnTimeout(events::OnTimeout { + amount: intent.amount_in, + token_mint: intent.token_in, + intent_id, + })) + .map_err(|err| { + msg!("{}", err); + ErrorCode::InvalidEventFormat + })?; + Ok(()) } } @@ -438,7 +523,7 @@ pub struct Auctioneer { // Define the Intent account with space calculation #[account] -#[derive(InitSpace)] +#[derive(Debug, PartialEq, Eq, InitSpace)] pub struct Intent { #[max_len(20)] pub intent_id: String, @@ -651,6 +736,8 @@ pub enum ErrorCode { InvalidSolverOutAddress, #[msg("Invalid hashed full denom")] InvalidHashedFullDenom, + #[msg("Invalid Event format. Check logs for more")] + InvalidEventFormat, #[msg("Unable to parse public key from string")] BadPublickey, } From 6126f31b5570c3c57307d77c103b37d55d7eebb9 Mon Sep 17 00:00:00 2001 From: Dhruv D Jain Date: Tue, 27 Aug 2024 13:40:52 +0100 Subject: [PATCH 28/47] fast-bridge: Timeouts (#381) If the solver is not able to solve the intent, then the escrowed funds can be issued back to the user. In case of single domain intents, the funds just get transferred to the user from the escrow account. But for cross chain intents, a timeout message is sent to the other chain with a flag of `Timeout` and the user who should receive it. The intent should store the user on source chain so that during timeout, we know whom to refund the funds to. For the memo, it is the same format and only the receiver is changed to user address instead of solver. --------- Co-authored-by: doradelta <64730977+doradelta@users.noreply.github.com> --- .../programs/bridge-escrow/src/bridge.rs | 245 +++++++++++++ .../programs/bridge-escrow/src/lib.rs | 345 +++++++----------- .../programs/bridge-escrow/src/tests.rs | 8 +- 3 files changed, 389 insertions(+), 209 deletions(-) create mode 100644 solana/bridge-escrow/programs/bridge-escrow/src/bridge.rs diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/bridge.rs b/solana/bridge-escrow/programs/bridge-escrow/src/bridge.rs new file mode 100644 index 00000000..556c18b5 --- /dev/null +++ b/solana/bridge-escrow/programs/bridge-escrow/src/bridge.rs @@ -0,0 +1,245 @@ +use std::str::FromStr; + +use anchor_lang::prelude::*; +use anchor_spl::token::{CloseAccount, MintTo}; +use ibc::apps::transfer::types::msgs::transfer::MsgTransfer; +use ibc::apps::transfer::types::packet::PacketData; +use ibc::apps::transfer::types::{PrefixedCoin, PrefixedDenom}; +use ibc::core::channel::types::timeout::TimeoutHeight; +use ibc::core::host::types::identifiers::{ChannelId, PortId}; +use ibc::core::primitives::Timestamp; +use ibc::primitives::Signer as IbcSigner; +use lib::hash::CryptoHash; +use solana_ibc::cpi::accounts::SendTransfer; +use solana_ibc::cpi::send_transfer; + +use crate::{ + ErrorCode, OnTimeout, SplTokenTransfer, DUMMY_TOKEN_TRANSFER_AMOUNT, +}; + +pub fn bridge_transfer( + accounts: BridgeTransferAccounts<'_>, + custom_memo: String, + hashed_full_denom: CryptoHash, + signer_seeds: &[&[&[u8]]], +) -> Result<()> { + let receiver_token_account = accounts.receiver_token_account; + + // Mint dummy tokens so that they can transferred + let mint_acc = MintTo { + mint: accounts.token_mint.clone(), + to: receiver_token_account.clone(), + authority: accounts.auctioneer_state, + }; + + let cpi_ctx = CpiContext::new_with_signer( + accounts.token_program.clone(), + mint_acc, + signer_seeds, + ); + + anchor_spl::token::mint_to(cpi_ctx, DUMMY_TOKEN_TRANSFER_AMOUNT)?; + + // Cross-chain transfer + memo + let transfer_ctx = CpiContext::new(accounts.ibc_program, SendTransfer { + sender: accounts.sender.clone(), + receiver: Some(accounts.receiver), + storage: accounts.storage, + trie: accounts.trie, + chain: accounts.chain, + mint_authority: Some(accounts.mint_authority), + token_mint: Some(accounts.token_mint.clone()), + escrow_account: Some(accounts.escrow_account), + receiver_token_account: Some(receiver_token_account.to_account_info()), + fee_collector: Some(accounts.fee_collector), + token_program: Some(accounts.token_program.clone()), + system_program: accounts.system_program, + }); + + let memo = "{\"forward\":{\"receiver\":\"\ + 0x4c22af5da4a849a8f39be00eb1b44676ac5c9060\",\"port\":\"\ + transfer\",\"channel\":\"channel-52\",\"timeout\":\ + 600000000000000,\"next\":{\"memo\":\"my-custom-msg\"}}}" + .to_string(); + let memo = memo.replace("my-custom-msg", &custom_memo); + + // MsgTransfer + let msg = MsgTransfer { + port_id_on_a: PortId::from_str("transfer").unwrap(), + chan_id_on_a: ChannelId::from_str("channel-1").unwrap(), + packet_data: PacketData { + token: PrefixedCoin { + denom: PrefixedDenom::from_str( + &accounts.token_mint.key().to_string(), + ) + .unwrap(), // token only owned by this PDA + amount: DUMMY_TOKEN_TRANSFER_AMOUNT.into(), + }, + sender: IbcSigner::from(accounts.sender.key().to_string()), + receiver: String::from("pfm").into(), + memo: memo.into(), + }, + timeout_height_on_b: TimeoutHeight::Never, + timeout_timestamp_on_b: Timestamp::from_nanoseconds(u64::MAX).unwrap(), + }; + + send_transfer(transfer_ctx, hashed_full_denom, msg)?; + + // Close the dummy token account. + let close_accs = CloseAccount { + account: receiver_token_account, + destination: accounts.sender.clone(), + authority: accounts.sender, + }; + + let cpi_ctx = CpiContext::new(accounts.token_program, close_accs); + + anchor_spl::token::close_account(cpi_ctx)?; + + Ok(()) +} + +pub struct BridgeTransferAccounts<'info> { + pub sender: AccountInfo<'info>, + pub auctioneer_state: AccountInfo<'info>, + pub receiver: AccountInfo<'info>, + pub storage: AccountInfo<'info>, + pub trie: AccountInfo<'info>, + pub chain: AccountInfo<'info>, + pub mint_authority: AccountInfo<'info>, + pub token_mint: AccountInfo<'info>, + pub escrow_account: AccountInfo<'info>, + pub receiver_token_account: AccountInfo<'info>, + pub fee_collector: AccountInfo<'info>, + pub ibc_program: AccountInfo<'info>, + pub token_program: AccountInfo<'info>, + pub system_program: AccountInfo<'info>, +} + +impl<'info> TryFrom<&mut SplTokenTransfer<'info>> + for BridgeTransferAccounts<'info> +{ + type Error = anchor_lang::error::Error; + + fn try_from(accounts: &mut SplTokenTransfer<'info>) -> Result { + Ok(Self { + sender: accounts.solver.to_account_info(), + auctioneer_state: accounts.auctioneer_state.to_account_info(), + receiver: accounts + .receiver + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), + storage: accounts + .storage + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), + trie: accounts + .trie + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), + chain: accounts + .chain + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), + mint_authority: accounts + .mint_authority + .as_ref() + .map(|acc| acc.to_account_info()) + .ok_or(ErrorCode::AccountsNotPresent)?, + token_mint: accounts + .token_mint + .as_ref() + .map(|acc| acc.to_account_info()) + .ok_or(ErrorCode::AccountsNotPresent)?, + escrow_account: accounts + .escrow_account + .as_ref() + .map(|acc| acc.to_account_info()) + .ok_or(ErrorCode::AccountsNotPresent)?, + receiver_token_account: accounts + .receiver_token_account + .as_ref() + .map(|acc| acc.to_account_info()) + .ok_or(ErrorCode::AccountsNotPresent)?, + fee_collector: accounts + .fee_collector + .as_ref() + .map(|acc| acc.to_account_info()) + .ok_or(ErrorCode::AccountsNotPresent)?, + ibc_program: accounts + .ibc_program + .as_ref() + .map(|acc| acc.to_account_info()) + .ok_or(ErrorCode::AccountsNotPresent)?, + token_program: accounts.token_program.to_account_info(), + system_program: accounts.system_program.to_account_info(), + }) + } +} + +impl<'info> TryFrom<&mut OnTimeout<'info>> for BridgeTransferAccounts<'info> { + type Error = anchor_lang::error::Error; + + fn try_from(accounts: &mut OnTimeout<'info>) -> Result { + Ok(Self { + sender: accounts.caller.to_account_info(), + auctioneer_state: accounts.auctioneer_state.to_account_info(), + receiver: accounts + .receiver + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), + storage: accounts + .storage + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), + trie: accounts + .trie + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), + chain: accounts + .chain + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), + mint_authority: accounts + .mint_authority + .as_ref() + .map(|acc| acc.to_account_info()) + .ok_or(ErrorCode::AccountsNotPresent)?, + token_mint: accounts + .token_mint + .as_ref() + .map(|acc| acc.to_account_info()) + .ok_or(ErrorCode::AccountsNotPresent)?, + escrow_account: accounts + .escrow_account + .as_ref() + .map(|acc| acc.to_account_info()) + .ok_or(ErrorCode::AccountsNotPresent)?, + receiver_token_account: accounts + .receiver_token_account + .as_ref() + .map(|acc| acc.to_account_info()) + .ok_or(ErrorCode::AccountsNotPresent)?, + fee_collector: accounts + .fee_collector + .as_ref() + .map(|acc| acc.to_account_info()) + .ok_or(ErrorCode::AccountsNotPresent)?, + ibc_program: accounts + .ibc_program + .as_ref() + .map(|acc| acc.to_account_info()) + .ok_or(ErrorCode::AccountsNotPresent)?, + token_program: accounts.token_program.to_account_info(), + system_program: accounts.system_program.to_account_info(), + }) + } +} diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index faeea579..bfdf1643 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -5,16 +5,8 @@ use anchor_lang::solana_program; use anchor_spl::associated_token::AssociatedToken; use anchor_spl::token; use anchor_spl::token::{Mint, Token, TokenAccount, Transfer as SplTransfer}; -use ibc::apps::transfer::types::msgs::transfer::MsgTransfer; -use ibc::apps::transfer::types::packet::PacketData; -use ibc::apps::transfer::types::{PrefixedCoin, PrefixedDenom}; -use ibc::core::host::types::identifiers::{ChannelId, PortId}; -use ibc::core::primitives::Timestamp; -use ibc::primitives::Signer as IbcSigner; use lib::hash::CryptoHash; use solana_ibc::chain; -use solana_ibc::cpi::accounts::SendTransfer; -use solana_ibc::cpi::send_transfer; use solana_ibc::program::SolanaIbc; use solana_ibc::storage::PrivateStorage; @@ -27,17 +19,15 @@ const DUMMY_SEED: &[u8] = b"dummy"; const DUMMY_TOKEN_TRANSFER_AMOUNT: u64 = 1; +pub mod bridge; pub mod events; #[cfg(test)] mod tests; -declare_id!("64K4AFty7UK9VJC6qykEVwFA93VoyND2uGyQgYa98ui9"); +declare_id!("AA1CoiekrMX3BjXZedX1KSj6p5VfeCcAf2WhmDcW31dg"); #[program] pub mod bridge_escrow { - use anchor_spl::token::{CloseAccount, MintTo}; - use ibc::core::channel::types::timeout::TimeoutHeight; - use super::*; /// Sets the authority and creates a token mint which would be used to @@ -108,7 +98,8 @@ pub mod bridge_escrow { ); intent.intent_id = new_intent.intent_id.clone(); - intent.user = new_intent.user_in; + intent.user_in = new_intent.user_in.clone(); + intent.user_out = new_intent.user_out; intent.token_in = new_intent.token_in; intent.amount_in = new_intent.amount_in; intent.token_out = new_intent.token_out.clone(); @@ -121,7 +112,8 @@ pub mod bridge_escrow { events::emit(events::Event::StoreIntent(events::StoreIntent { intent: Intent { intent_id: new_intent.intent_id, - user: new_intent.user_in, + user_in: new_intent.user_in, + user_out: new_intent.user_out, token_in: new_intent.token_in, amount_in: new_intent.amount_in, token_out: new_intent.token_out, @@ -218,14 +210,15 @@ pub mod bridge_escrow { hashed_full_denom: Option, solver_out: Option, ) -> Result<()> { - let intent = &ctx.accounts.intent; + let accounts = ctx.accounts; + let intent = accounts.intent.clone(); require!( - *ctx.accounts.solver.key == intent.winner_solver, + *accounts.solver.key == intent.winner_solver, ErrorCode::Unauthorized ); - let token_program = &ctx.accounts.token_program; - let solver = &ctx.accounts.solver; + let token_program = &accounts.token_program; + let solver = &accounts.solver; let amount_out = intent .amount_out @@ -234,12 +227,8 @@ pub mod bridge_escrow { // Transfer tokens from Solver to User let cpi_accounts = SplTransfer { - from: ctx - .accounts - .solver_token_out_account - .to_account_info() - .clone(), - to: ctx.accounts.user_token_out_account.to_account_info().clone(), + from: accounts.solver_token_out_account.to_account_info().clone(), + to: accounts.user_token_out_account.to_account_info().clone(), authority: solver.to_account_info().clone(), }; let cpi_program = token_program.to_account_info(); @@ -255,13 +244,11 @@ pub mod bridge_escrow { if intent.single_domain { // Transfer tokens from Auctioneer to Solver - let auctioneer_token_in_account = ctx - .accounts + let auctioneer_token_in_account = accounts .auctioneer_token_in_account .as_ref() .ok_or(ErrorCode::AccountsNotPresent)?; - let solver_token_in_account = ctx - .accounts + let solver_token_in_account = accounts .solver_token_in_account .as_ref() .ok_or(ErrorCode::AccountsNotPresent)?; @@ -269,7 +256,7 @@ pub mod bridge_escrow { let cpi_accounts = SplTransfer { from: auctioneer_token_in_account.to_account_info(), to: solver_token_in_account.to_account_info(), - authority: ctx.accounts.auctioneer_state.to_account_info(), + authority: accounts.auctioneer_state.to_account_info(), }; let cpi_program = token_program.to_account_info(); token::transfer( @@ -284,8 +271,8 @@ pub mod bridge_escrow { events::emit(events::Event::SendFundsToUser( events::SendFundsToUser { amount: amount_out, - receiver: intent.user, - token_mint: ctx.accounts.token_out.key(), + receiver: intent.user_out, + token_mint: accounts.token_out.key(), intent_id, solver_out, }, @@ -300,155 +287,28 @@ pub mod bridge_escrow { let hashed_full_denom = hashed_full_denom.ok_or(ErrorCode::InvalidTokenAddress)?; - let token_mint = ctx - .accounts - .token_mint - .as_ref() - .ok_or(ErrorCode::AccountsNotPresent)?; - let my_custom_memo = format!( "{},{},{}", - intent.token_out, intent.amount_out, solver_out + intent.token_in, intent.amount_in, solver_out ); + bridge::bridge_transfer( + accounts.try_into()?, + my_custom_memo, + hashed_full_denom, + signer_seeds, + )?; - let receiver_token_account = ctx - .accounts - .receiver_token_account + let token_mint = accounts + .token_mint .as_ref() .ok_or(ErrorCode::AccountsNotPresent)?; - // Mint dummy tokens so that they can transferred - let mint_acc = MintTo { - mint: token_mint.to_account_info(), - to: receiver_token_account.to_account_info(), - authority: ctx.accounts.auctioneer_state.to_account_info(), - }; - - let cpi_ctx = CpiContext::new_with_signer( - ctx.accounts.token_program.to_account_info(), - mint_acc, - signer_seeds, - ); - - anchor_spl::token::mint_to(cpi_ctx, DUMMY_TOKEN_TRANSFER_AMOUNT)?; - - // Cross-chain transfer + memo - let transfer_ctx = CpiContext::new_with_signer( - ctx.accounts - .ibc_program - .as_ref() - .ok_or(ErrorCode::AccountsNotPresent)? - .to_account_info(), - SendTransfer { - sender: ctx.accounts.solver.to_account_info(), - receiver: ctx - .accounts - .receiver - .as_ref() - .map(|acc| acc.to_account_info()), - storage: ctx - .accounts - .storage - .as_ref() - .ok_or(ErrorCode::AccountsNotPresent)? - .to_account_info(), - trie: ctx - .accounts - .trie - .as_ref() - .ok_or(ErrorCode::AccountsNotPresent)? - .to_account_info(), - chain: ctx - .accounts - .chain - .as_ref() - .ok_or(ErrorCode::AccountsNotPresent)? - .to_account_info(), - mint_authority: ctx - .accounts - .mint_authority - .as_ref() - .map(|acc| acc.to_account_info()), - token_mint: ctx - .accounts - .token_mint - .as_ref() - .map(|acc| acc.to_account_info()), - escrow_account: ctx - .accounts - .escrow_account - .as_ref() - .map(|acc| acc.to_account_info()), - receiver_token_account: Some( - receiver_token_account.to_account_info(), - ), - fee_collector: ctx - .accounts - .fee_collector - .as_ref() - .map(|acc| acc.to_account_info()), - token_program: Some( - ctx.accounts.token_program.to_account_info(), - ), - system_program: ctx - .accounts - .system_program - .to_account_info(), - }, - signer_seeds, - ); - - let memo = "{\"forward\":{\"receiver\":\"\ - 0x4c22af5da4a849a8f39be00eb1b44676ac5c9060\",\"port\":\ - \"transfer\",\"channel\":\"channel-52\",\"timeout\":\ - 600000000000000,\"next\":{\"memo\":\"my-custom-msg\"\ - }}}" - .to_string(); - let memo = memo.replace("my-custom-msg", &my_custom_memo); - - // MsgTransfer - let msg = MsgTransfer { - port_id_on_a: PortId::from_str("transfer").unwrap(), - chan_id_on_a: ChannelId::from_str("channel-0").unwrap(), - packet_data: PacketData { - token: PrefixedCoin { - denom: PrefixedDenom::from_str( - &token_mint.key().to_string(), - ) - .unwrap(), // token only owned by this PDA - amount: DUMMY_TOKEN_TRANSFER_AMOUNT.into(), - }, - sender: IbcSigner::from( - ctx.accounts.solver.key().to_string(), - ), - receiver: String::from("pfm").into(), - memo: memo.into(), - }, - timeout_height_on_b: TimeoutHeight::Never, - timeout_timestamp_on_b: Timestamp::from_nanoseconds(u64::MAX) - .unwrap(), - }; - - send_transfer(transfer_ctx, hashed_full_denom, msg)?; - - // Close the dummy token account. - let close_accs = CloseAccount { - account: receiver_token_account.to_account_info(), - destination: ctx.accounts.solver.to_account_info(), - authority: ctx.accounts.solver.to_account_info(), - }; - - let cpi_ctx = CpiContext::new( - ctx.accounts.token_program.to_account_info(), - close_accs, - ); - - anchor_spl::token::close_account(cpi_ctx)?; + // anchor_spl::token::close_account(cpi_ctx)?; events::emit(events::Event::SendFundsToUser( events::SendFundsToUser { amount: amount_out, - receiver: intent.user, - token_mint: ctx.accounts.token_out.key(), + receiver: intent.user_out, + token_mint: accounts.token_out.key(), intent_id, solver_out: Some(solver_out), }, @@ -462,20 +322,18 @@ pub mod bridge_escrow { Ok(()) } - /// If the intent has not been solved, then the funds can withdrawn by the user - /// after the timeout period has passed. + /// If the intent has not been solved, then the funds can be withdrawn by + /// the user after the timeout period has passed. /// - /// TODO: The funds should only be withdrawn if the message is sent through IBC that - /// the request got timed out. + /// For the cross chain intents, a message is sent to the source chain to unlock + /// the funds. pub fn on_timeout( ctx: Context, intent_id: String, ) -> Result<()> { - let authority = &ctx.accounts.user.key(); - - let intent = &ctx.accounts.intent; - require!(authority == &intent.user, ErrorCode::Unauthorized); + let authority = &ctx.accounts.caller.key(); + let intent = &ctx.accounts.intent.clone(); let current_time = Clock::get()?.unix_timestamp as u64; require!( current_time >= intent.timeout_timestamp_in_sec, @@ -487,29 +345,68 @@ pub mod bridge_escrow { let signer_seeds = signer_seeds.as_ref(); let signer_seeds = core::slice::from_ref(&signer_seeds); - // Unescrow the tokens - let cpi_accounts = SplTransfer { - from: ctx.accounts.escrow_token_account.to_account_info(), - to: ctx.accounts.user_token_account.to_account_info(), - authority: ctx.accounts.auctioneer_state.to_account_info(), - }; + if intent.single_domain { + let user_token_account = ctx + .accounts + .user_token_account + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)?; + let escrow_token_account = ctx + .accounts + .escrow_token_account + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)?; + require!( + user_token_account.owner == *authority, + ErrorCode::Unauthorized + ); - let cpi_ctx = CpiContext::new_with_signer( - ctx.accounts.token_program.to_account_info(), - cpi_accounts, - signer_seeds, - ); - anchor_spl::token::transfer(cpi_ctx, intent.amount_in)?; + // Unescrow the tokens + let cpi_accounts = SplTransfer { + from: escrow_token_account.to_account_info(), + to: user_token_account.to_account_info(), + authority: ctx.accounts.auctioneer_state.to_account_info(), + }; - events::emit(events::Event::OnTimeout(events::OnTimeout { - amount: intent.amount_in, - token_mint: intent.token_in, - intent_id, - })) - .map_err(|err| { - msg!("{}", err); - ErrorCode::InvalidEventFormat - })?; + let cpi_ctx = CpiContext::new_with_signer( + ctx.accounts.token_program.to_account_info(), + cpi_accounts, + signer_seeds, + ); + anchor_spl::token::transfer(cpi_ctx, intent.amount_in)?; + + events::emit(events::Event::OnTimeout(events::OnTimeout { + amount: intent.amount_in, + token_mint: intent.token_in, + intent_id, + })) + .map_err(|err| { + msg!("{}", err); + ErrorCode::InvalidEventFormat + })?; + } else { + // Send a cross domain message to the source chain to unlock the funds + let my_custom_memo = format!( + "{},{},{}", + intent.token_in, intent.amount_in, intent.user_in + ); + let token_mint = ctx + .accounts + .token_mint + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .key(); + + let hashed_full_denom = + CryptoHash::digest(token_mint.to_string().as_bytes()); + + bridge::bridge_transfer( + ctx.accounts.try_into()?, + my_custom_memo, + hashed_full_denom, + signer_seeds, + )?; + } Ok(()) } @@ -527,7 +424,11 @@ pub struct Auctioneer { pub struct Intent { #[max_len(20)] pub intent_id: String, - pub user: Pubkey, + // User on source chain + #[max_len(40)] + pub user_in: String, + // User on destination chain + pub user_out: Pubkey, pub token_in: Pubkey, pub amount_in: u64, #[max_len(20)] @@ -544,7 +445,8 @@ pub struct Intent { #[derive(AnchorSerialize, AnchorDeserialize, Debug)] pub struct IntentPayload { pub intent_id: String, - pub user_in: Pubkey, + pub user_in: String, + pub user_out: Pubkey, pub token_in: Pubkey, pub amount_in: u64, pub token_out: String, @@ -692,9 +594,8 @@ pub struct EscrowFunds<'info> { #[instruction(intent_id: String)] pub struct OnTimeout<'info> { #[account(mut)] - pub user: Signer<'info>, - #[account(mut, token::authority = user, token::mint = token_mint)] - pub user_token_account: Account<'info, TokenAccount>, + pub caller: Signer<'info>, + #[account(seeds = [AUCTIONEER_SEED], bump, constraint = auctioneer_state.authority == *auctioneer.key)] pub auctioneer_state: Account<'info, Auctioneer>, #[account(mut)] @@ -702,10 +603,42 @@ pub struct OnTimeout<'info> { pub auctioneer: UncheckedAccount<'info>, #[account(mut, close = auctioneer, seeds = [INTENT_SEED, intent_id.as_bytes()], bump)] pub intent: Account<'info, Intent>, - pub token_mint: Account<'info, Mint>, + + // Single domain transfer accounts + pub token_in: Option>, + #[account(mut, token::mint = token_mint)] + pub user_token_account: Option>, #[account(mut, token::mint = token_mint, token::authority = auctioneer_state)] - pub escrow_token_account: Account<'info, TokenAccount>, + pub escrow_token_account: Option>, + + // Cross chain transfer accounts + pub ibc_program: Option>, // Use IbcProgram here + #[account(mut)] + /// CHECK: + pub receiver: Option>, + #[account(mut)] + pub storage: Option>, + /// CHECK: + #[account(mut)] + pub trie: Option>, + #[account(mut)] + pub chain: Option>>, + /// CHECK: + #[account(mut)] + pub mint_authority: Option>, + #[account(mut, seeds = [DUMMY_SEED], bump)] + pub token_mint: Option>>, + /// CHECK: + #[account(mut)] + pub escrow_account: Option>, + #[account(init_if_needed, payer = caller, associated_token::mint = token_mint, associated_token::authority = caller)] + pub receiver_token_account: Option>>, + /// CHECK: + #[account(mut)] + pub fee_collector: Option>, + pub token_program: Program<'info, Token>, + pub associated_token_program: Program<'info, AssociatedToken>, pub system_program: Program<'info, System>, } diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index 6f5592a3..30fe9c0b 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -283,7 +283,8 @@ fn escrow_bridge_program() -> Result<()> { let new_intent = IntentPayload { intent_id: intent_id.clone(), - user_in: user.pubkey(), + user_in: user.pubkey().to_string(), + user_out: user.pubkey(), token_in, amount_in: TRANSFER_AMOUNT, token_out: token_out.to_string(), @@ -403,7 +404,8 @@ fn escrow_bridge_program() -> Result<()> { let new_intent = IntentPayload { intent_id: intent_id.clone(), - user_in: user.pubkey(), + user_in: user.pubkey().to_string(), + user_out: user.pubkey(), token_in, amount_in: TRANSFER_AMOUNT, token_out: token_out.to_string(), @@ -488,7 +490,7 @@ fn escrow_bridge_program() -> Result<()> { associated_token_program: anchor_spl::associated_token::ID, system_program: anchor_lang::solana_program::system_program::ID, ibc_program: Some(solana_ibc::ID), - receiver: None, + receiver: Some(user.pubkey()), storage: Some(storage), trie: Some(trie), chain: Some(chain), From 89a44de683f33e0b4c4b4ee95a69d78b2e8ddbb9 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Tue, 27 Aug 2024 22:53:35 +0530 Subject: [PATCH 29/47] remove intent from on receive transfer method --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index bfdf1643..05aee683 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -487,15 +487,12 @@ pub struct StoreIntent<'info> { } #[derive(Accounts)] -#[instruction(intent_id: String)] pub struct ReceiveTransferContext<'info> { #[account(mut)] pub authority: Signer<'info>, #[account(seeds = [AUCTIONEER_SEED], bump, has_one = authority)] pub auctioneer_state: Account<'info, Auctioneer>, - #[account(mut, close = authority, seeds = [INTENT_SEED, intent_id.as_bytes()], bump)] - pub intent: Account<'info, Intent>, pub token_mint: Account<'info, Mint>, #[account(mut, token::mint = token_mint, token::authority = auctioneer_state)] From 43b99085147a1e795a57271de5dfe5b0ae14c5f5 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Tue, 27 Aug 2024 23:36:10 +0530 Subject: [PATCH 30/47] add timeout and on receive methods in tests --- .../programs/bridge-escrow/src/tests.rs | 98 +++++++++++++++++-- 1 file changed, 91 insertions(+), 7 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index 30fe9c0b..d408e372 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -374,17 +374,17 @@ fn escrow_bridge_program() -> Result<()> { sol_rpc_client.get_token_account_balance(&user_token_out_addr).unwrap(); assert_eq!( - ((solver_token_in_balance_after.ui_amount.unwrap() - - solver_token_in_balance_before.ui_amount.unwrap()) * - 1_000_000f64) + ((solver_token_in_balance_after.ui_amount.unwrap() + - solver_token_in_balance_before.ui_amount.unwrap()) + * 1_000_000f64) .round() as u64, TRANSFER_AMOUNT ); assert_eq!( - ((user_token_out_balance_after.ui_amount.unwrap() - - user_token_out_balance_before.ui_amount.unwrap()) * - 1_000_000f64) + ((user_token_out_balance_after.ui_amount.unwrap() + - user_token_out_balance_before.ui_amount.unwrap()) + * 1_000_000f64) .round() as u64, amount_out ); @@ -501,7 +501,7 @@ fn escrow_bridge_program() -> Result<()> { fee_collector: Some(fee_collector), }) .args(crate::instruction::SendFundsToUser { - intent_id, + intent_id: intent_id.clone(), hashed_full_denom: Some(hashed_full_denom), // Solver out doesnt matter for this test solver_out: Some(Pubkey::new_unique().to_string()), @@ -513,5 +513,89 @@ fn escrow_bridge_program() -> Result<()> { ..RpcSendTransactionConfig::default() })?; println!(" Signature: {sig}"); + + // on receive funds + let sig = program + .request() + .accounts(crate::accounts::ReceiveTransferContext { + auctioneer_state, + authority: auctioneer.pubkey(), + escrow_token_account: token_in_escrow_addr, + token_mint: token_in, + solver_token_account: solver_token_in_addr, + token_program: anchor_spl::token::ID, + instruction: crate::solana_program::sysvar::instructions::ID, + }) + .args(crate::instruction::OnReceiveTransfer { memo: "".to_string() }) + .payer(auctioneer.clone()) + .signer(&*auctioneer) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..RpcSendTransactionConfig::default() + })?; + println!(" Signature: {sig}"); + + // on timeout (single domain) + let sig = program + .request() + .accounts(crate::accounts::OnTimeout { + caller: auctioneer.pubkey(), + auctioneer_state, + intent: intent_state, + auctioneer: auctioneer.pubkey(), + token_in: Some(token_in), + user_token_account: Some(user_token_out_addr), + escrow_token_account: Some(token_in_escrow_addr), + token_program: anchor_spl::token::ID, + associated_token_program: anchor_spl::associated_token::ID, + system_program: anchor_lang::solana_program::system_program::ID, + ibc_program: None, + storage: None, + trie: None, + chain: None, + mint_authority: None, + token_mint: None, + escrow_account: None, + receiver_token_account: None, + fee_collector: None, + receiver: None, + }) + .args(crate::instruction::OnTimeout { intent_id: intent_id.clone() }) + .payer(auctioneer.clone()) + .signer(&*auctioneer) + .send_with_spinner_and_config(RpcSendTransactionConfig::default())?; + println!(" Signature: {sig}"); + + // on timeout (cross domain) + let sig = program + .request() + .accounts(crate::accounts::OnTimeout { + caller: auctioneer.pubkey(), + auctioneer_state, + intent: intent_state, + auctioneer: auctioneer.pubkey(), + token_in: None, + user_token_account: None, + escrow_token_account: None, + token_program: anchor_spl::token::ID, + associated_token_program: anchor_spl::associated_token::ID, + system_program: anchor_lang::solana_program::system_program::ID, + ibc_program: Some(solana_ibc::ID), + storage: Some(storage), + trie: Some(trie), + chain: Some(chain), + mint_authority: Some(mint_authority), + token_mint: Some(dummy_token_mint), + escrow_account: Some(escrow_account), + receiver_token_account: Some(receiver_token_account), + fee_collector: Some(fee_collector), + receiver: Some(user.pubkey()), + }) + .args(crate::instruction::OnTimeout { intent_id: intent_id.clone() }) + .payer(auctioneer.clone()) + .signer(&*auctioneer) + .send_with_spinner_and_config(RpcSendTransactionConfig::default())?; + println!(" Signature: {sig}"); + Ok(()) } From 0772575dbb8871b6a89c29d39f332432473b3918 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Wed, 28 Aug 2024 21:05:13 +0530 Subject: [PATCH 31/47] change token in to string instead of pubkey --- .../bridge-escrow/programs/bridge-escrow/src/events.rs | 2 +- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 9 +++++---- solana/bridge-escrow/programs/bridge-escrow/src/tests.rs | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/events.rs b/solana/bridge-escrow/programs/bridge-escrow/src/events.rs index f0213003..20167e96 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/events.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/events.rs @@ -102,7 +102,7 @@ pub struct SendFundsToUser { )] pub struct OnTimeout { pub amount: u64, - pub token_mint: Pubkey, + pub token_mint: String, pub intent_id: String, } diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 05aee683..256b0639 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -100,7 +100,7 @@ pub mod bridge_escrow { intent.intent_id = new_intent.intent_id.clone(); intent.user_in = new_intent.user_in.clone(); intent.user_out = new_intent.user_out; - intent.token_in = new_intent.token_in; + intent.token_in = new_intent.token_in.clone(); intent.amount_in = new_intent.amount_in; intent.token_out = new_intent.token_out.clone(); intent.timeout_timestamp_in_sec = new_intent.timeout_timestamp_in_sec; @@ -377,7 +377,7 @@ pub mod bridge_escrow { events::emit(events::Event::OnTimeout(events::OnTimeout { amount: intent.amount_in, - token_mint: intent.token_in, + token_mint: intent.token_in.clone(), intent_id, })) .map_err(|err| { @@ -429,7 +429,8 @@ pub struct Intent { pub user_in: String, // User on destination chain pub user_out: Pubkey, - pub token_in: Pubkey, + #[max_len(40)] + pub token_in: String, pub amount_in: u64, #[max_len(20)] pub token_out: String, @@ -447,7 +448,7 @@ pub struct IntentPayload { pub intent_id: String, pub user_in: String, pub user_out: Pubkey, - pub token_in: Pubkey, + pub token_in: String, pub amount_in: u64, pub token_out: String, pub amount_out: String, diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index d408e372..fea65c6c 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -285,7 +285,7 @@ fn escrow_bridge_program() -> Result<()> { intent_id: intent_id.clone(), user_in: user.pubkey().to_string(), user_out: user.pubkey(), - token_in, + token_in: token_in.to_string(), amount_in: TRANSFER_AMOUNT, token_out: token_out.to_string(), amount_out: amount_out.to_string(), @@ -406,7 +406,7 @@ fn escrow_bridge_program() -> Result<()> { intent_id: intent_id.clone(), user_in: user.pubkey().to_string(), user_out: user.pubkey(), - token_in, + token_in: token_in.to_string(), amount_in: TRANSFER_AMOUNT, token_out: token_out.to_string(), amount_out: amount_out.to_string(), From 7bfa98838c2282834af5b63d79048266df955a52 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Thu, 29 Aug 2024 16:13:19 +0530 Subject: [PATCH 32/47] set arbitrary space --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 256b0639..60c6d37e 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -480,7 +480,7 @@ pub struct Initialize<'info> { pub struct StoreIntent<'info> { #[account(mut)] pub authority: Signer<'info>, - #[account(init, seeds = [INTENT_SEED, intent_id.as_bytes()], bump, payer = authority, space = 8 + Intent::INIT_SPACE)] + #[account(init, seeds = [INTENT_SEED, intent_id.as_bytes()], bump, payer = authority, space = 3000)] pub intent: Account<'info, Intent>, #[account(seeds = [AUCTIONEER_SEED], bump)] pub auctioneer: Account<'info, Auctioneer>, From 4902f261c9b632e838efad021a4cb1835e5db42e Mon Sep 17 00:00:00 2001 From: dhruvja Date: Fri, 30 Aug 2024 18:52:48 +0530 Subject: [PATCH 33/47] allocate accounts to heap --- .../programs/bridge-escrow/src/lib.rs | 18 +++++++++--------- test_keypair.json | 1 + 2 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 test_keypair.json diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 60c6d37e..0e3dc960 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -514,9 +514,9 @@ pub struct ReceiveTransferContext<'info> { pub struct SplTokenTransfer<'info> { // Intent reading #[account(mut, close = auctioneer, seeds = [INTENT_SEED, intent_id.as_bytes()], bump)] - pub intent: Account<'info, Intent>, + pub intent: Box>, #[account(seeds = [AUCTIONEER_SEED], bump)] - pub auctioneer_state: Account<'info, Auctioneer>, + pub auctioneer_state: Box>, #[account(mut)] pub solver: Signer<'info>, @@ -524,20 +524,20 @@ pub struct SplTokenTransfer<'info> { /// CHECK: pub auctioneer: UncheckedAccount<'info>, - pub token_in: Option>, - pub token_out: Account<'info, Mint>, + pub token_in: Option>>, + pub token_out: Box>, // Program (Escrow) -> Solver SPL Token Transfer Accounts #[account(mut, token::mint = token_in, token::authority = auctioneer_state)] - pub auctioneer_token_in_account: Option>, + pub auctioneer_token_in_account: Option>>, #[account(mut, token::authority = solver, token::mint = token_in)] - pub solver_token_in_account: Option>, + pub solver_token_in_account: Option>>, // Solver -> User SPL Token Transfer Accounts #[account(mut, token::authority = solver, token::mint = token_out)] - pub solver_token_out_account: Account<'info, TokenAccount>, + pub solver_token_out_account: Box>, #[account(mut, token::mint = token_out)] - pub user_token_out_account: Account<'info, TokenAccount>, + pub user_token_out_account: Box>, pub token_program: Program<'info, Token>, pub associated_token_program: Program<'info, AssociatedToken>, @@ -551,7 +551,7 @@ pub struct SplTokenTransfer<'info> { /// CHECK: pub receiver: Option>, #[account(mut)] - pub storage: Option>, + pub storage: Option>>, /// CHECK: #[account(mut)] pub trie: Option>, diff --git a/test_keypair.json b/test_keypair.json new file mode 100644 index 00000000..7463fa58 --- /dev/null +++ b/test_keypair.json @@ -0,0 +1 @@ +[27, 12, 51, 61, 10, 40, 230, 225, 108, 38, 117, 91, 214, 20, 71, 94, 53, 177, 102, 39, 47, 129, 198, 152, 44, 189, 250, 152, 146, 96, 189, 7, 177, 120, 41, 10, 9, 188, 193, 176, 101, 233, 169, 42, 240, 231, 237, 224, 51, 236, 6, 85, 19, 10, 209, 85, 72, 2, 193, 78, 211, 20, 180, 85] \ No newline at end of file From 4b6e54c566ce5a10897c5dbb68035d6a7297884a Mon Sep 17 00:00:00 2001 From: dhruvja Date: Sat, 31 Aug 2024 18:10:17 +0530 Subject: [PATCH 34/47] use intent payload instead of string --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 4 ++-- test_keypair.json | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 test_keypair.json diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 0e3dc960..4a8ccaeb 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -476,11 +476,11 @@ pub struct Initialize<'info> { // Define the context for storing intent #[derive(Accounts)] -#[instruction(intent_id: String)] +#[instruction(intent: IntentPayload)] pub struct StoreIntent<'info> { #[account(mut)] pub authority: Signer<'info>, - #[account(init, seeds = [INTENT_SEED, intent_id.as_bytes()], bump, payer = authority, space = 3000)] + #[account(init, seeds = [INTENT_SEED, intent.intent_id.as_bytes()], bump, payer = authority, space = 3000)] pub intent: Account<'info, Intent>, #[account(seeds = [AUCTIONEER_SEED], bump)] pub auctioneer: Account<'info, Auctioneer>, diff --git a/test_keypair.json b/test_keypair.json deleted file mode 100644 index 7463fa58..00000000 --- a/test_keypair.json +++ /dev/null @@ -1 +0,0 @@ -[27, 12, 51, 61, 10, 40, 230, 225, 108, 38, 117, 91, 214, 20, 71, 94, 53, 177, 102, 39, 47, 129, 198, 152, 44, 189, 250, 152, 146, 96, 189, 7, 177, 120, 41, 10, 9, 188, 193, 176, 101, 233, 169, 42, 240, 231, 237, 224, 51, 236, 6, 85, 19, 10, 209, 85, 72, 2, 193, 78, 211, 20, 180, 85] \ No newline at end of file From 098691321e613191d0b9dd44d9285a01bbc239bc Mon Sep 17 00:00:00 2001 From: doradelta <64730977+doradelta@users.noreply.github.com> Date: Sun, 1 Sep 2024 17:52:24 +0200 Subject: [PATCH 35/47] Update lib.rs --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 4a8ccaeb..156e37ed 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -476,11 +476,11 @@ pub struct Initialize<'info> { // Define the context for storing intent #[derive(Accounts)] -#[instruction(intent: IntentPayload)] +#[instruction(intent_payload: IntentPayload)] pub struct StoreIntent<'info> { #[account(mut)] pub authority: Signer<'info>, - #[account(init, seeds = [INTENT_SEED, intent.intent_id.as_bytes()], bump, payer = authority, space = 3000)] + #[account(init, seeds = [INTENT_SEED, intent_payload.intent_id.as_bytes()], bump, payer = authority, space = 3000)] pub intent: Account<'info, Intent>, #[account(seeds = [AUCTIONEER_SEED], bump)] pub auctioneer: Account<'info, Auctioneer>, From 9e63faba2635c09f994d12c7efa82f4d1bf8f466 Mon Sep 17 00:00:00 2001 From: doradelta <64730977+doradelta@users.noreply.github.com> Date: Sun, 1 Sep 2024 20:33:01 +0200 Subject: [PATCH 36/47] Update lib.rs --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 156e37ed..01168b6e 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -24,7 +24,7 @@ pub mod events; #[cfg(test)] mod tests; -declare_id!("AA1CoiekrMX3BjXZedX1KSj6p5VfeCcAf2WhmDcW31dg"); +declare_id!("yAJJJMZmjWSQjvq8WuARKygH8KJkeQTXB5BGJBJcR4T"); #[program] pub mod bridge_escrow { From dcab6ba891bdc27833d196297a5c644c00667822 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Mon, 2 Sep 2024 19:41:44 +0530 Subject: [PATCH 37/47] hardcode solana ibc address --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 01168b6e..259cb8d6 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -11,7 +11,7 @@ use solana_ibc::program::SolanaIbc; use solana_ibc::storage::PrivateStorage; // const DUMMY: &str = "0x36dd1bfe89d409f869fabbe72c3cf72ea8b460f6"; -// const BRIDGE_CONTRACT_PUBKEY: &str = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"; +const BRIDGE_CONTRACT_PUBKEY: &str = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"; const AUCTIONEER_SEED: &[u8] = b"auctioneer"; const INTENT_SEED: &[u8] = b"intent"; @@ -546,7 +546,9 @@ pub struct SplTokenTransfer<'info> { // The accounts below are only needed for cross chain intents // Cross-chain Transfer Accounts - pub ibc_program: Option>, // Use IbcProgram here + #[account(address = Pubkey::from_str(BRIDGE_CONTRACT_PUBKEY).unwrap())] + /// CHECK: + pub ibc_program: Option>, // Use IbcProgram here #[account(mut)] /// CHECK: pub receiver: Option>, @@ -610,7 +612,9 @@ pub struct OnTimeout<'info> { pub escrow_token_account: Option>, // Cross chain transfer accounts - pub ibc_program: Option>, // Use IbcProgram here + #[account(address = Pubkey::from_str(BRIDGE_CONTRACT_PUBKEY).unwrap())] + /// CHECK: + pub ibc_program: Option>, // Use IbcProgram here #[account(mut)] /// CHECK: pub receiver: Option>, From 1603619f3d8e56bd169e3eb4d32635964483e973 Mon Sep 17 00:00:00 2001 From: doradelta <64730977+doradelta@users.noreply.github.com> Date: Mon, 2 Sep 2024 17:40:52 +0200 Subject: [PATCH 38/47] Update lib.rs --- solana/solana-ibc/programs/solana-ibc/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solana/solana-ibc/programs/solana-ibc/src/lib.rs b/solana/solana-ibc/programs/solana-ibc/src/lib.rs index f284173e..d35dab81 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/lib.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/lib.rs @@ -37,7 +37,7 @@ declare_id!("EUiJni1BZFL3BhaWcS7NTJmqWyh8NwRLjBzrcGBvxKU4"); #[cfg(not(feature = "mocks"))] mod relayer { - anchor_lang::declare_id!("Ao2wBFe6VzG5B1kQKkNw4grnPRQZNpP4wwQW86vXGxpY"); + anchor_lang::declare_id!("2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"); } mod allocator; From 5c569baf6980dc43cb26551dd5cd3ec5ba8283d2 Mon Sep 17 00:00:00 2001 From: doradelta <64730977+doradelta@users.noreply.github.com> Date: Mon, 2 Sep 2024 17:54:54 +0200 Subject: [PATCH 39/47] Update lib.rs --- solana/solana-ibc/programs/solana-ibc/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solana/solana-ibc/programs/solana-ibc/src/lib.rs b/solana/solana-ibc/programs/solana-ibc/src/lib.rs index d35dab81..aa58c9c9 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/lib.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/lib.rs @@ -33,11 +33,11 @@ pub const WSOL_ADDRESS: &str = "So11111111111111111111111111111111111111112"; pub const MINIMUM_FEE_ACCOUNT_BALANCE: u64 = solana_program::native_token::LAMPORTS_PER_SOL; -declare_id!("EUiJni1BZFL3BhaWcS7NTJmqWyh8NwRLjBzrcGBvxKU4"); +declare_id!("2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"); #[cfg(not(feature = "mocks"))] mod relayer { - anchor_lang::declare_id!("2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"); + anchor_lang::declare_id!("Ao2wBFe6VzG5B1kQKkNw4grnPRQZNpP4wwQW86vXGxpY"); } mod allocator; From e938903ccbbb7b833a3b58081588787f48e70877 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Tue, 3 Sep 2024 11:53:50 +0530 Subject: [PATCH 40/47] avoid deserialization of solana ibc accounts --- .../programs/bridge-escrow/src/bridge.rs | 50 +++++++------- .../programs/bridge-escrow/src/lib.rs | 65 ++++++++++++------- .../programs/bridge-escrow/src/tests.rs | 12 ++-- 3 files changed, 72 insertions(+), 55 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/bridge.rs b/solana/bridge-escrow/programs/bridge-escrow/src/bridge.rs index 556c18b5..6ce641c5 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/bridge.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/bridge.rs @@ -50,7 +50,7 @@ pub fn bridge_transfer( mint_authority: Some(accounts.mint_authority), token_mint: Some(accounts.token_mint.clone()), escrow_account: Some(accounts.escrow_account), - receiver_token_account: Some(receiver_token_account.to_account_info()), + receiver_token_account: Some(receiver_token_account.clone()), fee_collector: Some(accounts.fee_collector), token_program: Some(accounts.token_program.clone()), system_program: accounts.system_program, @@ -148,33 +148,33 @@ impl<'info> TryFrom<&mut SplTokenTransfer<'info>> mint_authority: accounts .mint_authority .as_ref() - .map(|acc| acc.to_account_info()) - .ok_or(ErrorCode::AccountsNotPresent)?, + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), token_mint: accounts .token_mint .as_ref() - .map(|acc| acc.to_account_info()) - .ok_or(ErrorCode::AccountsNotPresent)?, + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), escrow_account: accounts .escrow_account .as_ref() - .map(|acc| acc.to_account_info()) - .ok_or(ErrorCode::AccountsNotPresent)?, + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), receiver_token_account: accounts .receiver_token_account .as_ref() - .map(|acc| acc.to_account_info()) - .ok_or(ErrorCode::AccountsNotPresent)?, + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), fee_collector: accounts .fee_collector .as_ref() - .map(|acc| acc.to_account_info()) - .ok_or(ErrorCode::AccountsNotPresent)?, + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), ibc_program: accounts .ibc_program .as_ref() - .map(|acc| acc.to_account_info()) - .ok_or(ErrorCode::AccountsNotPresent)?, + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), token_program: accounts.token_program.to_account_info(), system_program: accounts.system_program.to_account_info(), }) @@ -211,33 +211,33 @@ impl<'info> TryFrom<&mut OnTimeout<'info>> for BridgeTransferAccounts<'info> { mint_authority: accounts .mint_authority .as_ref() - .map(|acc| acc.to_account_info()) - .ok_or(ErrorCode::AccountsNotPresent)?, + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), token_mint: accounts .token_mint .as_ref() - .map(|acc| acc.to_account_info()) - .ok_or(ErrorCode::AccountsNotPresent)?, + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), escrow_account: accounts .escrow_account .as_ref() - .map(|acc| acc.to_account_info()) - .ok_or(ErrorCode::AccountsNotPresent)?, + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), receiver_token_account: accounts .receiver_token_account .as_ref() - .map(|acc| acc.to_account_info()) - .ok_or(ErrorCode::AccountsNotPresent)?, + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), fee_collector: accounts .fee_collector .as_ref() - .map(|acc| acc.to_account_info()) - .ok_or(ErrorCode::AccountsNotPresent)?, + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), ibc_program: accounts .ibc_program .as_ref() - .map(|acc| acc.to_account_info()) - .ok_or(ErrorCode::AccountsNotPresent)?, + .ok_or(ErrorCode::AccountsNotPresent)? + .to_account_info(), token_program: accounts.token_program.to_account_info(), system_program: accounts.system_program.to_account_info(), }) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 259cb8d6..79f358c6 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -6,12 +6,10 @@ use anchor_spl::associated_token::AssociatedToken; use anchor_spl::token; use anchor_spl::token::{Mint, Token, TokenAccount, Transfer as SplTransfer}; use lib::hash::CryptoHash; -use solana_ibc::chain; -use solana_ibc::program::SolanaIbc; -use solana_ibc::storage::PrivateStorage; // const DUMMY: &str = "0x36dd1bfe89d409f869fabbe72c3cf72ea8b460f6"; -const BRIDGE_CONTRACT_PUBKEY: &str = "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"; +const BRIDGE_CONTRACT_PUBKEY: &str = + "2HLLVco5HvwWriNbUhmVwA2pCetRkpgrqwnjcsZdyTKT"; const AUCTIONEER_SEED: &[u8] = b"auctioneer"; const INTENT_SEED: &[u8] = b"intent"; @@ -207,6 +205,7 @@ pub mod bridge_escrow { pub fn send_funds_to_user( ctx: Context, intent_id: String, + // Unused parameter hashed_full_denom: Option, solver_out: Option, ) -> Result<()> { @@ -284,8 +283,14 @@ pub mod bridge_escrow { } else { let solver_out = solver_out.ok_or(ErrorCode::InvalidSolverAddress)?; + let token_mint = accounts + .token_mint + .as_ref() + .ok_or(ErrorCode::AccountsNotPresent)? + .key(); + let hashed_full_denom = - hashed_full_denom.ok_or(ErrorCode::InvalidTokenAddress)?; + CryptoHash::digest(token_mint.to_string().as_bytes()); let my_custom_memo = format!( "{},{},{}", @@ -298,12 +303,6 @@ pub mod bridge_escrow { signer_seeds, )?; - let token_mint = accounts - .token_mint - .as_ref() - .ok_or(ErrorCode::AccountsNotPresent)?; - - // anchor_spl::token::close_account(cpi_ctx)?; events::emit(events::Event::SendFundsToUser( events::SendFundsToUser { amount: amount_out, @@ -406,6 +405,16 @@ pub mod bridge_escrow { hashed_full_denom, signer_seeds, )?; + + events::emit(events::Event::OnTimeout(events::OnTimeout { + amount: intent.amount_in, + token_mint: intent.token_in.clone(), + intent_id, + })) + .map_err(|err| { + msg!("{}", err); + ErrorCode::InvalidEventFormat + })?; } Ok(()) @@ -548,27 +557,31 @@ pub struct SplTokenTransfer<'info> { // Cross-chain Transfer Accounts #[account(address = Pubkey::from_str(BRIDGE_CONTRACT_PUBKEY).unwrap())] /// CHECK: - pub ibc_program: Option>, // Use IbcProgram here + pub ibc_program: Option>, #[account(mut)] /// CHECK: pub receiver: Option>, + /// CHECK: validated by solana-ibc program #[account(mut)] - pub storage: Option>>, + pub storage: Option>, /// CHECK: #[account(mut)] pub trie: Option>, + /// CHECK: validated by solana-ibc program #[account(mut)] - pub chain: Option>>, + pub chain: Option>, /// CHECK: #[account(mut)] pub mint_authority: Option>, + /// CHECK: validated by solana-ibc program #[account(mut, seeds = [DUMMY_SEED], bump)] - pub token_mint: Option>>, + pub token_mint: Option>, /// CHECK: #[account(mut)] pub escrow_account: Option>, - #[account(init_if_needed, payer = solver, associated_token::mint = token_mint, associated_token::authority = solver)] - pub receiver_token_account: Option>>, + /// CHECK: validated by solana-ibc program + #[account(mut)] + pub receiver_token_account: Option>, /// CHECK: #[account(mut)] pub fee_collector: Option>, @@ -611,30 +624,34 @@ pub struct OnTimeout<'info> { #[account(mut, token::mint = token_mint, token::authority = auctioneer_state)] pub escrow_token_account: Option>, - // Cross chain transfer accounts + // Cross-chain Transfer Accounts #[account(address = Pubkey::from_str(BRIDGE_CONTRACT_PUBKEY).unwrap())] /// CHECK: - pub ibc_program: Option>, // Use IbcProgram here + pub ibc_program: Option>, #[account(mut)] /// CHECK: pub receiver: Option>, + /// CHECK: validated by solana-ibc program #[account(mut)] - pub storage: Option>, + pub storage: Option>, /// CHECK: #[account(mut)] pub trie: Option>, + /// CHECK: validated by solana-ibc program #[account(mut)] - pub chain: Option>>, + pub chain: Option>, /// CHECK: #[account(mut)] pub mint_authority: Option>, + /// CHECK: validated by solana-ibc program #[account(mut, seeds = [DUMMY_SEED], bump)] - pub token_mint: Option>>, + pub token_mint: Option>, /// CHECK: #[account(mut)] pub escrow_account: Option>, - #[account(init_if_needed, payer = caller, associated_token::mint = token_mint, associated_token::authority = caller)] - pub receiver_token_account: Option>>, + /// CHECK: validated by solana-ibc program + #[account(mut)] + pub receiver_token_account: Option>, /// CHECK: #[account(mut)] pub fee_collector: Option>, diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index fea65c6c..55ea91b3 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -374,17 +374,17 @@ fn escrow_bridge_program() -> Result<()> { sol_rpc_client.get_token_account_balance(&user_token_out_addr).unwrap(); assert_eq!( - ((solver_token_in_balance_after.ui_amount.unwrap() - - solver_token_in_balance_before.ui_amount.unwrap()) - * 1_000_000f64) + ((solver_token_in_balance_after.ui_amount.unwrap() - + solver_token_in_balance_before.ui_amount.unwrap()) * + 1_000_000f64) .round() as u64, TRANSFER_AMOUNT ); assert_eq!( - ((user_token_out_balance_after.ui_amount.unwrap() - - user_token_out_balance_before.ui_amount.unwrap()) - * 1_000_000f64) + ((user_token_out_balance_after.ui_amount.unwrap() - + user_token_out_balance_before.ui_amount.unwrap()) * + 1_000_000f64) .round() as u64, amount_out ); From 3acbc6f5ad5341d0481bd096f0a8348d90500a29 Mon Sep 17 00:00:00 2001 From: banegil Date: Tue, 3 Sep 2024 13:52:31 +0200 Subject: [PATCH 41/47] change token_mint & receiver_token_account on SplTokenTransfer struct --- .../bridge-escrow/programs/bridge-escrow/src/lib.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 79f358c6..e7dbea97 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -575,13 +575,18 @@ pub struct SplTokenTransfer<'info> { pub mint_authority: Option>, /// CHECK: validated by solana-ibc program #[account(mut, seeds = [DUMMY_SEED], bump)] - pub token_mint: Option>, + pub token_mint: Option>>, /// CHECK: #[account(mut)] pub escrow_account: Option>, /// CHECK: validated by solana-ibc program - #[account(mut)] - pub receiver_token_account: Option>, + #[account( + init_if_needed, + payer = solver, + associated_token::mint = token_mint, + associated_token::authority = auctioneer_state + )] + pub receiver_token_account: Option>, /// CHECK: #[account(mut)] pub fee_collector: Option>, From 8639a56eed51e516e273810fe517154ec31c679e Mon Sep 17 00:00:00 2001 From: dhruvja Date: Tue, 3 Sep 2024 17:58:28 +0530 Subject: [PATCH 42/47] box mint and receiver token account --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index e7dbea97..9a049e48 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -584,9 +584,9 @@ pub struct SplTokenTransfer<'info> { init_if_needed, payer = solver, associated_token::mint = token_mint, - associated_token::authority = auctioneer_state + associated_token::authority = solver )] - pub receiver_token_account: Option>, + pub receiver_token_account: Option>>, /// CHECK: #[account(mut)] pub fee_collector: Option>, @@ -650,13 +650,13 @@ pub struct OnTimeout<'info> { pub mint_authority: Option>, /// CHECK: validated by solana-ibc program #[account(mut, seeds = [DUMMY_SEED], bump)] - pub token_mint: Option>, + pub token_mint: Option>>, /// CHECK: #[account(mut)] pub escrow_account: Option>, /// CHECK: validated by solana-ibc program - #[account(mut)] - pub receiver_token_account: Option>, + #[account(init_if_needed, payer = caller, associated_token::mint = token_mint, associated_token::authority = caller)] + pub receiver_token_account: Option>>, /// CHECK: #[account(mut)] pub fee_collector: Option>, From 346c2f1a4f5b9810ccd9342271bd36bb9a2c30b0 Mon Sep 17 00:00:00 2001 From: doradelta <64730977+doradelta@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:55:46 +0200 Subject: [PATCH 43/47] Update lib.rs --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 9a049e48..0a74e5a6 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -15,7 +15,7 @@ const AUCTIONEER_SEED: &[u8] = b"auctioneer"; const INTENT_SEED: &[u8] = b"intent"; const DUMMY_SEED: &[u8] = b"dummy"; -const DUMMY_TOKEN_TRANSFER_AMOUNT: u64 = 1; +const DUMMY_TOKEN_TRANSFER_AMOUNT: u64 = 1_000_000_000; pub mod bridge; pub mod events; From a5438346ffc7824d447c09fad6c1970a536ffb97 Mon Sep 17 00:00:00 2001 From: doradelta <64730977+doradelta@users.noreply.github.com> Date: Tue, 3 Sep 2024 21:17:40 +0200 Subject: [PATCH 44/47] Update bridge.rs --- solana/bridge-escrow/programs/bridge-escrow/src/bridge.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/bridge.rs b/solana/bridge-escrow/programs/bridge-escrow/src/bridge.rs index 6ce641c5..19abefb0 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/bridge.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/bridge.rs @@ -94,7 +94,7 @@ pub fn bridge_transfer( let cpi_ctx = CpiContext::new(accounts.token_program, close_accs); - anchor_spl::token::close_account(cpi_ctx)?; + // anchor_spl::token::close_account(cpi_ctx)?; Ok(()) } From 82d6fcc3d59a3c45352e2d75a5dd945d7d551ddc Mon Sep 17 00:00:00 2001 From: doradelta <64730977+doradelta@users.noreply.github.com> Date: Fri, 20 Sep 2024 18:09:14 +0200 Subject: [PATCH 45/47] Update lib.rs --- solana/bridge-escrow/programs/bridge-escrow/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 0a74e5a6..1ae1d4d9 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -205,8 +205,6 @@ pub mod bridge_escrow { pub fn send_funds_to_user( ctx: Context, intent_id: String, - // Unused parameter - hashed_full_denom: Option, solver_out: Option, ) -> Result<()> { let accounts = ctx.accounts; From 6d034580b404ac66d2a696f746b6754cee723c3f Mon Sep 17 00:00:00 2001 From: doradelta <64730977+doradelta@users.noreply.github.com> Date: Tue, 24 Sep 2024 12:14:50 +0200 Subject: [PATCH 46/47] Update lib.rs --- .../programs/bridge-escrow/src/lib.rs | 366 ++++++++++++------ 1 file changed, 254 insertions(+), 112 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 1ae1d4d9..08838806 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -43,58 +43,60 @@ pub mod bridge_escrow { /// The funds are stored in token account owned by the auctioneer state PDA. Right now /// all the deposits are present in a single pool. But we would want to deposit the funds /// in seperate account so that we dont touch the funds of other users. - /// - /// TODO: Store the intent without `amount_out` and `solver_out` which would then be - /// updated by auctioneer. Also escrow the funds in an account whose seeds are the - /// intent id. - pub fn escrow_funds(ctx: Context, amount: u64) -> Result<()> { - // Transfer SPL tokens from the user's account to the auctioneer's account + pub fn escrow_and_store_intent( + ctx: Context, + amount: u64, + new_intent: IntentPayload + ) -> Result<()> { + // Step 1: Check the conditions (translated from Solidity) + + require!( + ctx.accounts.intent.user_in == "", + ErrorCode::IntentAlreadyExists + ); + + require!( + new_intent.winner_solver == Pubkey::default(), + ErrorCode::WinnerSolverMustBeEmpty + ); + + require!( + new_intent.user_in == ctx.accounts.user.key().to_string(), + ErrorCode::SrcUserNotSender + ); + + // Step 2: Escrow the funds (same as before) + let cpi_accounts = SplTransfer { from: ctx.accounts.user_token_account.to_account_info(), to: ctx.accounts.escrow_token_account.to_account_info(), authority: ctx.accounts.user.to_account_info(), }; - + let cpi_program = ctx.accounts.token_program.to_account_info(); let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts); - + token::transfer(cpi_ctx, amount)?; - + events::emit(events::Event::EscrowFunds(events::EscrowFunds { amount, sender: ctx.accounts.user.key(), token_mint: ctx.accounts.token_mint.key(), - })) - .map_err(|err| { + })).map_err(|err| { msg!("{}", err); ErrorCode::InvalidEventFormat })?; - - Ok(()) - } - - /// Called by the auctioneer whose address is stored in `auctioneer` state account. - pub fn store_intent( - ctx: Context, - new_intent: IntentPayload, - ) -> Result<()> { - // verify if caller is auctioneer - let auctioneer = &ctx.accounts.auctioneer; - require!( - *ctx.accounts.authority.key == auctioneer.authority, - ErrorCode::Unauthorized - ); - - // save intent on a PDA derived from the auctioneer account + + // Step 3: Store the intent (same as before) + let intent = &mut ctx.accounts.intent; - let current_timestamp = Clock::get()?.unix_timestamp as u64; - + require!( current_timestamp < new_intent.timeout_timestamp_in_sec, ErrorCode::InvalidTimeout ); - + intent.intent_id = new_intent.intent_id.clone(); intent.user_in = new_intent.user_in.clone(); intent.user_out = new_intent.user_out; @@ -106,7 +108,7 @@ pub mod bridge_escrow { intent.amount_out = new_intent.amount_out.clone(); intent.winner_solver = new_intent.winner_solver; intent.single_domain = new_intent.single_domain; - + events::emit(events::Event::StoreIntent(events::StoreIntent { intent: Intent { intent_id: new_intent.intent_id, @@ -121,11 +123,49 @@ pub mod bridge_escrow { timeout_timestamp_in_sec: new_intent.timeout_timestamp_in_sec, single_domain: new_intent.single_domain, }, - })) - .map_err(|err| { + })).map_err(|err| { msg!("{}", err); ErrorCode::InvalidEventFormat })?; + + Ok(()) + } + + pub fn update_auction_data( + ctx: Context, + intent_id: String, + amount_out: String, + winner_solver: Pubkey, + ) -> Result<()> { + // Retrieve the intent from the provided context + let intent = &mut ctx.accounts.intent; + + // Ensure that the auctioneer is the signer + require!( + ctx.accounts.auctioneer.authority == ctx.accounts.authority.key(), + ErrorCode::Unauthorized + ); + + // Verify that the intent ID matches the expected one + require!( + intent.intent_id == intent_id, + ErrorCode::IntentDoesNotExist + ); + + // Update the auction data + intent.amount_out = amount_out; + intent.winner_solver = winner_solver; + + // Emit an event for the auction data update (optional) + // events::emit(events::Event::UpdateAuctionData { + // intent_id, + // amount_out, + // winner_solver: winner_solver.to_string(), + // }) + // .map_err(|err| { + // msg!("{}", err); + // ErrorCode::InvalidEventFormat + // })?; Ok(()) } @@ -141,34 +181,24 @@ pub mod bridge_escrow { ctx: Context, memo: String, ) -> Result<()> { - // Extract and validate the memo + // Split and extract memo fields let parts: Vec<&str> = memo.split(',').collect(); - - // require!( - // msg.packet_data.token.denom.base_denom.to_string() == DUMMY, - // ErrorCode::InvalidDenom - // ); - let token_mint = - Pubkey::from_str(parts[0]).map_err(|_| ErrorCode::BadPublickey)?; - let amount: u64 = - parts[1].parse().map_err(|_| ErrorCode::InvalidAmount)?; - let solver = - Pubkey::from_str(parts[2]).map_err(|_| ErrorCode::BadPublickey)?; - - if token_mint != ctx.accounts.token_mint.key() { - return Err(ErrorCode::InvalidTokenAddress.into()); - } - - if solver != ctx.accounts.solver_token_account.owner { - return Err(ErrorCode::InvalidSolverOutAddress.into()); - } - - // Transfer tokens from Auctioneer to Solver - let cpi_accounts = SplTransfer { - from: ctx.accounts.escrow_token_account.to_account_info(), - to: ctx.accounts.solver_token_account.to_account_info(), - authority: ctx.accounts.auctioneer_state.to_account_info(), - }; + require!(parts.len() == 7, ErrorCode::InvalidMemoFormat); // Ensure memo has 7 parts + + // Memo format: , , , , , , + let withdraw_user_flag: bool = parts[0].parse().map_err(|_| ErrorCode::InvalidWithdrawFlag)?; + let intent_id = parts[1]; + let from = Pubkey::from_str(parts[2]).map_err(|_| ErrorCode::BadPublickey)?; + let token_mint = Pubkey::from_str(parts[3]).map_err(|_| ErrorCode::BadPublickey)?; + let to = Pubkey::from_str(parts[4]).map_err(|_| ErrorCode::BadPublickey)?; + let amount: u64 = parts[5].parse().map_err(|_| ErrorCode::InvalidAmount)?; + // let solver_out = Pubkey::from_str(parts[6]).map_err(|_| ErrorCode::BadPublickey)?; + + // Retrieve the intent from the provided context + let intent = &mut ctx.accounts.intent; + + // Validate the intent + require!(intent.intent_id == intent_id, ErrorCode::IntentDoesNotExist); let seeds = &[ AUCTIONEER_SEED, @@ -177,51 +207,92 @@ pub mod bridge_escrow { let seeds = seeds.as_ref(); let signer_seeds = core::slice::from_ref(&seeds); - let cpi_program = ctx.accounts.token_program.to_account_info(); - let cpi_ctx = CpiContext::new_with_signer( - cpi_program, - cpi_accounts, - signer_seeds, - ); - - token::transfer(cpi_ctx, amount)?; - - events::emit(events::Event::OnReceiveTransfer( - events::OnReceiveTransfer { - amount, - solver: ctx.accounts.solver_token_account.owner, - }, - )) - .map_err(|err| { - msg!("{}", err); - ErrorCode::InvalidEventFormat - })?; - + if withdraw_user_flag { + // Case 1: User withdrawal + require!( + intent.user_out == from, + ErrorCode::IntentMismatchFromUser + ); + + // Transfer tokens from the escrow account to the user's token account + let cpi_accounts = SplTransfer { + from: ctx.accounts.escrow_token_account.to_account_info(), + to: ctx.accounts.solver_token_account.to_account_info(), + authority: ctx.accounts.auctioneer_state.to_account_info(), + }; + + let cpi_program = ctx.accounts.token_program.to_account_info(); + let cpi_ctx = CpiContext::new_with_signer(cpi_program, cpi_accounts, signer_seeds); + + token::transfer(cpi_ctx, amount)?; + + } else { + // Case 2: Solver transaction + require!( + intent.winner_solver == from, + ErrorCode::IntentMismatchFromSolver + ); + require!( + intent.token_out == token_mint.to_string(), + ErrorCode::InvalidTokenOut + ); + require!( + intent.user_out == to, + ErrorCode::IntentMismatchToUser + ); + require!( + intent.amount_out.parse::().unwrap() <= amount, + ErrorCode::InsufficientAmount + ); + + // Transfer tokens from the escrow account to the solver's token account + let cpi_accounts = SplTransfer { + from: ctx.accounts.escrow_token_account.to_account_info(), + to: ctx.accounts.solver_token_account.to_account_info(), + authority: ctx.accounts.auctioneer_state.to_account_info(), + }; + + let cpi_program = ctx.accounts.token_program.to_account_info(); + let cpi_ctx = CpiContext::new_with_signer(cpi_program, cpi_accounts, signer_seeds); + + token::transfer(cpi_ctx, amount)?; + } + + // Emit event based on the action performed + // events::emit(events::Event::OnReceiveTransfer( + // events::OnReceiveTransfer { + // amount, + // solver: if withdraw_user_flag { + // ctx.accounts.solver_token_account.owner + // } else { + // ctx.accounts.solver_token_account.owner + // }, + // }, + // )) + // .map_err(|err| { + // msg!("{}", err); + // ErrorCode::InvalidEventFormat + // })?; + Ok(()) } + + // this function is called by Solver #[allow(unused_variables)] pub fn send_funds_to_user( ctx: Context, intent_id: String, + amount_out: u64, solver_out: Option, + single_domain: bool ) -> Result<()> { let accounts = ctx.accounts; - let intent = accounts.intent.clone(); - require!( - *accounts.solver.key == intent.winner_solver, - ErrorCode::Unauthorized - ); let token_program = &accounts.token_program; let solver = &accounts.solver; - let amount_out = intent - .amount_out - .parse::() - .map_err(|_| ErrorCode::InvalidAmount)?; - // Transfer tokens from Solver to User let cpi_accounts = SplTransfer { from: accounts.solver_token_out_account.to_account_info().clone(), @@ -239,7 +310,18 @@ pub mod bridge_escrow { let seeds = seeds.as_ref(); let signer_seeds = core::slice::from_ref(&seeds); - if intent.single_domain { + if single_domain { + let intent = accounts.intent.clone(); + require!( + *accounts.solver.key == intent.winner_solver, + ErrorCode::Unauthorized + ); + + let amount_out = intent + .amount_out + .parse::() + .map_err(|_| ErrorCode::InvalidAmount)?; + // Transfer tokens from Auctioneer to Solver let auctioneer_token_in_account = accounts .auctioneer_token_in_account @@ -290,9 +372,22 @@ pub mod bridge_escrow { let hashed_full_denom = CryptoHash::digest(token_mint.to_string().as_bytes()); + // bool withdraw_user, + // string intentId, + // string from, + // string token, + // string to, + // string amount, + // string solver_out + let my_custom_memo = format!( - "{},{},{}", - intent.token_in, intent.amount_in, solver_out + "0,{},{},{},{},{},{}", + intent_id, + accounts.solver.key, + accounts.token_out.key(), + accounts.user_token_out_account.owner, + amount_out, + solver_out ); bridge::bridge_transfer( accounts.try_into()?, @@ -304,7 +399,7 @@ pub mod bridge_escrow { events::emit(events::Event::SendFundsToUser( events::SendFundsToUser { amount: amount_out, - receiver: intent.user_out, + receiver: accounts.user_token_out_account.owner, token_mint: accounts.token_out.key(), intent_id, solver_out: Some(solver_out), @@ -324,7 +419,7 @@ pub mod bridge_escrow { /// /// For the cross chain intents, a message is sent to the source chain to unlock /// the funds. - pub fn on_timeout( + pub fn user_cancel_intent( ctx: Context, intent_id: String, ) -> Result<()> { @@ -384,8 +479,8 @@ pub mod bridge_escrow { } else { // Send a cross domain message to the source chain to unlock the funds let my_custom_memo = format!( - "{},{},{}", - intent.token_in, intent.amount_in, intent.user_in + "{},{}", + intent_id, authority ); let token_mint = ctx .accounts @@ -481,20 +576,8 @@ pub struct Initialize<'info> { pub associated_token_program: Program<'info, AssociatedToken>, } -// Define the context for storing intent -#[derive(Accounts)] -#[instruction(intent_payload: IntentPayload)] -pub struct StoreIntent<'info> { - #[account(mut)] - pub authority: Signer<'info>, - #[account(init, seeds = [INTENT_SEED, intent_payload.intent_id.as_bytes()], bump, payer = authority, space = 3000)] - pub intent: Account<'info, Intent>, - #[account(seeds = [AUCTIONEER_SEED], bump)] - pub auctioneer: Account<'info, Auctioneer>, - pub system_program: Program<'info, System>, -} - #[derive(Accounts)] +#[instruction(intent_id: String)] pub struct ReceiveTransferContext<'info> { #[account(mut)] pub authority: Signer<'info>, @@ -512,9 +595,37 @@ pub struct ReceiveTransferContext<'info> { /// CHECK: Used for getting the caller program id to verify if the right /// program is calling the method. pub instruction: UncheckedAccount<'info>, + pub token_program: Program<'info, Token>, + + // New Intent account addition + #[account( + mut, + seeds = [b"intent", intent_id.as_bytes()], + bump, + constraint = intent.user_in == authority.key().to_string() + )] + pub intent: Account<'info, Intent>, } +#[derive(Accounts)] +#[instruction(intent_id: String)] +pub struct UpdateAuctionData<'info> { + #[account(mut)] + pub authority: Signer<'info>, + + #[account( + seeds = [AUCTIONEER_SEED], + bump, + has_one = authority // Ensures that the authority is the auctioneer + )] + pub auctioneer: Account<'info, Auctioneer>, + + #[account(mut, seeds = [INTENT_SEED, intent_id.as_bytes()], bump)] + pub intent: Account<'info, Intent>, +} + + // Accounts for transferring SPL tokens #[derive(Accounts)] #[instruction(intent_id: String)] @@ -591,7 +702,9 @@ pub struct SplTokenTransfer<'info> { } #[derive(Accounts)] -pub struct EscrowFunds<'info> { +#[instruction(intent_payload: IntentPayload)] +pub struct EscrowAndStoreIntent<'info> { + // From EscrowFunds #[account(mut)] pub user: Signer<'info>, #[account(mut, token::authority = user, token::mint = token_mint)] @@ -601,11 +714,18 @@ pub struct EscrowFunds<'info> { pub token_mint: Account<'info, Mint>, #[account(init_if_needed, payer = user, associated_token::mint = token_mint, associated_token::authority = auctioneer_state)] pub escrow_token_account: Account<'info, TokenAccount>, + + // From StoreIntent + #[account(init, seeds = [INTENT_SEED, intent_payload.intent_id.as_bytes()], bump, payer = user, space = 3000)] + pub intent: Account<'info, Intent>, + + // Shared Programs pub token_program: Program<'info, Token>, pub associated_token_program: Program<'info, AssociatedToken>, pub system_program: Program<'info, System>, } + #[derive(Accounts)] #[instruction(intent_id: String)] pub struct OnTimeout<'info> { @@ -695,4 +815,26 @@ pub enum ErrorCode { InvalidEventFormat, #[msg("Unable to parse public key from string")] BadPublickey, + #[msg("Intent already exists.")] + IntentAlreadyExists, + #[msg("WinnerSolver must be an empty string.")] + WinnerSolverMustBeEmpty, + #[msg("Source user does not match the sender.")] + SrcUserNotSender, + #[msg("Invalid withdraw flag format.")] + InvalidWithdrawFlag, + #[msg("Intent does not exist.")] + IntentDoesNotExist, + #[msg("Intent mismatch: 'from' address does not match expected intent.dstUser.")] + IntentMismatchFromUser, + #[msg("Intent mismatch: 'from' address does not match expected intent.winnerSolver.")] + IntentMismatchFromSolver, + #[msg("Intent mismatch: 'to' address does not match expected intent.dstUser.")] + IntentMismatchToUser, + #[msg("Insufficient amount provided.")] + InsufficientAmount, + #[msg("Invalid Memo format")] + InvalidMemoFormat, + #[msg("Invalid token out")] + InvalidTokenOut } From d843604e1a027c53abe06dfd211da754bec4521a Mon Sep 17 00:00:00 2001 From: doradelta <64730977+doradelta@users.noreply.github.com> Date: Wed, 25 Sep 2024 13:15:56 +0200 Subject: [PATCH 47/47] Update tests.rs --- .../programs/bridge-escrow/src/tests.rs | 509 ++++++++---------- 1 file changed, 222 insertions(+), 287 deletions(-) diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index 55ea91b3..1322ac6c 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -226,25 +226,56 @@ fn escrow_bridge_program() -> Result<()> { let token_in_escrow_addr = get_associated_token_address(&auctioneer_state, &token_in); - // Escrow user funds - println!("\nEscrow user funds for single domain"); + // Escrow user funds and store intent (combined) + println!("\nEscrow user funds and store intent for single domain"); - // let user_token_in_balance_before = - // sol_rpc_client.get_token_account_balance(&user_token_in_addr).unwrap(); + let intent_id = "123456789".to_string(); + // Define amount_out (this would typically come from the intent) + let amount_out = 10000; // This should match what’s expected in the intent + // Find the Program Derived Address (PDA) for the intent account + let intent_state = Pubkey::find_program_address( + &[crate::INTENT_SEED, intent_id.as_bytes()], + &crate::ID, + ) + .0; + + // Get the current timestamp + let current_timestamp = + SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); + + // Define the new intent payload + let new_intent = IntentPayload { + intent_id: intent_id.clone(), + user_in: user.pubkey().to_string(), // Must match the ctx.accounts.user key in the contract + user_out: user.pubkey(), + token_in: token_in.to_string(), + amount_in: TRANSFER_AMOUNT, + token_out: token_out.to_string(), + amount_out: amount_out.to_string(), // Amount out as a string + timeout_timestamp_in_sec: current_timestamp + 10000, // Arbitrary timeout + winner_solver: Pubkey::default(), // Ensure winner_solver is empty at first + single_domain: true, + }; + + // Call the escrow_and_store_intent() function let sig = program .request() - .accounts(crate::accounts::EscrowFunds { + .accounts(crate::accounts::EscrowAndStoreIntent { user: user.pubkey(), user_token_account: user_token_in_addr, auctioneer_state, token_mint: token_in, escrow_token_account: token_in_escrow_addr, + intent: intent_state, token_program: anchor_spl::token::ID, associated_token_program: associated_token::ID, system_program: system_program::ID, }) - .args(crate::instruction::EscrowFunds { amount: TRANSFER_AMOUNT }) + .args(crate::instruction::EscrowAndStoreIntent { + amount: TRANSFER_AMOUNT, + new_intent, + }) .payer(user.clone()) .signer(&*user) .send_with_spinner_and_config(RpcSendTransactionConfig { @@ -252,80 +283,47 @@ fn escrow_bridge_program() -> Result<()> { ..Default::default() }) .unwrap(); - println!(" Signature: {}", sig); - - // let user_token_in_balance_after = - // sol_rpc_client.get_token_account_balance(&user_token_in_addr).unwrap(); - // assert_eq!( - // ((user_token_in_balance_after.ui_amount.unwrap() - // - user_token_in_balance_before.ui_amount.unwrap()) - // * 1_000_000f64) - // .round() as u64, - // TRANSFER_AMOUNT - // ); - - // Store the intent - println!("\nStore the intent for single domain"); - let intent_id = "12323542".to_string(); + println!(" Signature: {}", sig); - // arbitrary value - let amount_out = 10000; + // Test for the update_auction_data function (only auctioneer can call this) + println!("\nTesting update_auction_data function"); - let intent_state = Pubkey::find_program_address( - &[crate::INTENT_SEED, intent_id.as_bytes()], - &crate::ID, - ) - .0; - - let current_timestamp = - SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); - - let new_intent = IntentPayload { - intent_id: intent_id.clone(), - user_in: user.pubkey().to_string(), - user_out: user.pubkey(), - token_in: token_in.to_string(), - amount_in: TRANSFER_AMOUNT, - token_out: token_out.to_string(), - amount_out: amount_out.to_string(), - timeout_timestamp_in_sec: current_timestamp + 10000, - winner_solver: solver.pubkey(), - single_domain: true, - }; + // New auction data + let amount_out = 10_000; // This should match what’s expected in the intent + let winner_solver = solver.pubkey(); // A new winner solver public key + // Only auctioneer should be able to call this function let sig = program .request() - .accounts(crate::accounts::StoreIntent { - authority: auctioneer.pubkey(), - intent: intent_state, + .accounts(crate::accounts::UpdateAuctionData { + authority: auctioneer.pubkey(), // Must be auctioneer auctioneer: auctioneer_state, - system_program: anchor_lang::solana_program::system_program::ID, + intent: intent_state, + }) + .args(crate::instruction::UpdateAuctionData { + intent_id: intent_id.clone(), + amount_out: amount_out.clone().to_string(), + winner_solver: winner_solver, }) - .args(crate::instruction::StoreIntent { new_intent }) .payer(auctioneer.clone()) .signer(&*auctioneer) .send_with_spinner_and_config(RpcSendTransactionConfig { skip_preflight: true, - ..Default::default() + ..RpcSendTransactionConfig::default() }) .unwrap(); + println!(" Signature: {}", sig); - // Send funds to user ( single domain ) + // Send funds to user (single domain) println!("\nSend funds to user single domain"); - let solver_token_in_addr = - get_associated_token_address(&solver.pubkey(), &token_in); - let user_token_out_addr = - get_associated_token_address(&user.pubkey(), &token_out); - - let solver_token_in_balance_before = sol_rpc_client - .get_token_account_balance(&solver_token_in_addr) - .unwrap(); - let user_token_out_balance_before = - sol_rpc_client.get_token_account_balance(&user_token_out_addr).unwrap(); + // Get the associated token addresses for the solver and the user + let solver_token_in_addr = get_associated_token_address(&solver.pubkey(), &token_in); + let user_token_out_addr = get_associated_token_address(&user.pubkey(), &token_out); + // Call the `send_funds_to_user` function let sig = program .request() .accounts(crate::accounts::SplTokenTransfer { @@ -342,6 +340,7 @@ fn escrow_bridge_program() -> Result<()> { token_program: anchor_spl::token::ID, associated_token_program: anchor_spl::associated_token::ID, system_program: anchor_lang::solana_program::system_program::ID, + // Cross-chain related fields, set to None since it's single domain ibc_program: None, receiver: None, storage: None, @@ -355,8 +354,9 @@ fn escrow_bridge_program() -> Result<()> { }) .args(crate::instruction::SendFundsToUser { intent_id: intent_id.clone(), - hashed_full_denom: None, - solver_out: None, + amount_out, // Pass the amount to transfer to the user + solver_out: None, // Set to None since this is a single domain transaction + single_domain: true, // Indicating that this is a single domain transaction }) .payer(solver.clone()) .signer(&*solver) @@ -365,237 +365,172 @@ fn escrow_bridge_program() -> Result<()> { ..Default::default() }) .unwrap(); - println!(" Signature: {}", sig); - - let solver_token_in_balance_after = sol_rpc_client - .get_token_account_balance(&solver_token_in_addr) - .unwrap(); - let user_token_out_balance_after = - sol_rpc_client.get_token_account_balance(&user_token_out_addr).unwrap(); - - assert_eq!( - ((solver_token_in_balance_after.ui_amount.unwrap() - - solver_token_in_balance_before.ui_amount.unwrap()) * - 1_000_000f64) - .round() as u64, - TRANSFER_AMOUNT - ); - - assert_eq!( - ((user_token_out_balance_after.ui_amount.unwrap() - - user_token_out_balance_before.ui_amount.unwrap()) * - 1_000_000f64) - .round() as u64, - amount_out - ); - - // Store the intent - println!("\nStore the intent for cross domain"); - let intent_id = "12323543".to_string(); - // arbitrary value - let amount_out = 10000; - - let intent_state = Pubkey::find_program_address( - &[crate::INTENT_SEED, intent_id.as_bytes()], - &crate::ID, - ) - .0; - - let new_intent = IntentPayload { - intent_id: intent_id.clone(), - user_in: user.pubkey().to_string(), - user_out: user.pubkey(), - token_in: token_in.to_string(), - amount_in: TRANSFER_AMOUNT, - token_out: token_out.to_string(), - amount_out: amount_out.to_string(), - timeout_timestamp_in_sec: current_timestamp + 10000, - winner_solver: solver.pubkey(), - single_domain: false, - }; - - let sig = program - .request() - .accounts(crate::accounts::StoreIntent { - authority: auctioneer.pubkey(), - intent: intent_state, - auctioneer: auctioneer_state, - system_program: anchor_lang::solana_program::system_program::ID, - }) - .args(crate::instruction::StoreIntent { new_intent }) - .payer(auctioneer.clone()) - .signer(&*auctioneer) - .send_with_spinner_and_config(RpcSendTransactionConfig { - skip_preflight: true, - ..Default::default() - }) - .unwrap(); println!(" Signature: {}", sig); - // Send funds to user ( cross domain ) - println!("\nSend funds to user cross domain"); - - let hashed_full_denom = - lib::hash::CryptoHash::digest(&dummy_token_mint.to_string().as_bytes()); - - println!("\nNative token mint {}", dummy_token_mint); - println!("hashed full denom {}", hashed_full_denom); - - // Derive the necessary accounts - let (storage, _bump_storage) = Pubkey::find_program_address( - &[solana_ibc::SOLANA_IBC_STORAGE_SEED], - &solana_ibc::ID, - ); - let (trie, _bump_trie) = - Pubkey::find_program_address(&[solana_ibc::TRIE_SEED], &solana_ibc::ID); - let (chain, _bump_chain) = Pubkey::find_program_address( - &[solana_ibc::CHAIN_SEED], - &solana_ibc::ID, - ); - let (mint_authority, _bump_mint_authority) = Pubkey::find_program_address( - &[solana_ibc::MINT_ESCROW_SEED], - &solana_ibc::ID, - ); - let (escrow_account, _bump_escrow_account) = Pubkey::find_program_address( - &[solana_ibc::ESCROW, &hashed_full_denom.as_slice()], - &solana_ibc::ID, - ); - - let (fee_collector, _bump_fee_collector) = - Pubkey::find_program_address(&[solana_ibc::FEE_SEED], &solana_ibc::ID); + // // Send funds to user ( cross domain ) + // println!("\nSend funds to user cross domain"); - let receiver_token_account = - get_associated_token_address(&solver.pubkey(), &dummy_token_mint); + // let hashed_full_denom = + // lib::hash::CryptoHash::digest(&dummy_token_mint.to_string().as_bytes()); - // Build and send the transaction to call send_funds_to_user - println!("\nSending funds to user"); - let sig = program - .request() - .instruction(ComputeBudgetInstruction::set_compute_unit_limit( - 1_000_000, - )) - .accounts(crate::accounts::SplTokenTransfer { - intent: intent_state, - auctioneer_state, - solver: solver.pubkey(), - auctioneer: auctioneer.pubkey(), - token_in: None, - token_out, - auctioneer_token_in_account: None, - solver_token_in_account: None, - solver_token_out_account: solver_token_out_addr, - user_token_out_account: user_token_out_addr, - token_program: anchor_spl::token::ID, - associated_token_program: anchor_spl::associated_token::ID, - system_program: anchor_lang::solana_program::system_program::ID, - ibc_program: Some(solana_ibc::ID), - receiver: Some(user.pubkey()), - storage: Some(storage), - trie: Some(trie), - chain: Some(chain), - mint_authority: Some(mint_authority), - token_mint: Some(dummy_token_mint), - escrow_account: Some(escrow_account), - receiver_token_account: Some(receiver_token_account), - fee_collector: Some(fee_collector), - }) - .args(crate::instruction::SendFundsToUser { - intent_id: intent_id.clone(), - hashed_full_denom: Some(hashed_full_denom), - // Solver out doesnt matter for this test - solver_out: Some(Pubkey::new_unique().to_string()), - }) - .payer(solver.clone()) - .signer(&*solver) - .send_with_spinner_and_config(RpcSendTransactionConfig { - skip_preflight: true, - ..RpcSendTransactionConfig::default() - })?; - println!(" Signature: {sig}"); - - // on receive funds - let sig = program - .request() - .accounts(crate::accounts::ReceiveTransferContext { - auctioneer_state, - authority: auctioneer.pubkey(), - escrow_token_account: token_in_escrow_addr, - token_mint: token_in, - solver_token_account: solver_token_in_addr, - token_program: anchor_spl::token::ID, - instruction: crate::solana_program::sysvar::instructions::ID, - }) - .args(crate::instruction::OnReceiveTransfer { memo: "".to_string() }) - .payer(auctioneer.clone()) - .signer(&*auctioneer) - .send_with_spinner_and_config(RpcSendTransactionConfig { - skip_preflight: true, - ..RpcSendTransactionConfig::default() - })?; - println!(" Signature: {sig}"); + // println!("\nNative token mint {}", dummy_token_mint); + // println!("hashed full denom {}", hashed_full_denom); - // on timeout (single domain) - let sig = program - .request() - .accounts(crate::accounts::OnTimeout { - caller: auctioneer.pubkey(), - auctioneer_state, - intent: intent_state, - auctioneer: auctioneer.pubkey(), - token_in: Some(token_in), - user_token_account: Some(user_token_out_addr), - escrow_token_account: Some(token_in_escrow_addr), - token_program: anchor_spl::token::ID, - associated_token_program: anchor_spl::associated_token::ID, - system_program: anchor_lang::solana_program::system_program::ID, - ibc_program: None, - storage: None, - trie: None, - chain: None, - mint_authority: None, - token_mint: None, - escrow_account: None, - receiver_token_account: None, - fee_collector: None, - receiver: None, - }) - .args(crate::instruction::OnTimeout { intent_id: intent_id.clone() }) - .payer(auctioneer.clone()) - .signer(&*auctioneer) - .send_with_spinner_and_config(RpcSendTransactionConfig::default())?; - println!(" Signature: {sig}"); + // // Derive the necessary accounts + // let (storage, _bump_storage) = Pubkey::find_program_address( + // &[solana_ibc::SOLANA_IBC_STORAGE_SEED], + // &solana_ibc::ID, + // ); + // let (trie, _bump_trie) = + // Pubkey::find_program_address(&[solana_ibc::TRIE_SEED], &solana_ibc::ID); + // let (chain, _bump_chain) = Pubkey::find_program_address( + // &[solana_ibc::CHAIN_SEED], + // &solana_ibc::ID, + // ); + // let (mint_authority, _bump_mint_authority) = Pubkey::find_program_address( + // &[solana_ibc::MINT_ESCROW_SEED], + // &solana_ibc::ID, + // ); + // let (escrow_account, _bump_escrow_account) = Pubkey::find_program_address( + // &[solana_ibc::ESCROW, &hashed_full_denom.as_slice()], + // &solana_ibc::ID, + // ); - // on timeout (cross domain) - let sig = program - .request() - .accounts(crate::accounts::OnTimeout { - caller: auctioneer.pubkey(), - auctioneer_state, - intent: intent_state, - auctioneer: auctioneer.pubkey(), - token_in: None, - user_token_account: None, - escrow_token_account: None, - token_program: anchor_spl::token::ID, - associated_token_program: anchor_spl::associated_token::ID, - system_program: anchor_lang::solana_program::system_program::ID, - ibc_program: Some(solana_ibc::ID), - storage: Some(storage), - trie: Some(trie), - chain: Some(chain), - mint_authority: Some(mint_authority), - token_mint: Some(dummy_token_mint), - escrow_account: Some(escrow_account), - receiver_token_account: Some(receiver_token_account), - fee_collector: Some(fee_collector), - receiver: Some(user.pubkey()), - }) - .args(crate::instruction::OnTimeout { intent_id: intent_id.clone() }) - .payer(auctioneer.clone()) - .signer(&*auctioneer) - .send_with_spinner_and_config(RpcSendTransactionConfig::default())?; - println!(" Signature: {sig}"); + // let (fee_collector, _bump_fee_collector) = + // Pubkey::find_program_address(&[solana_ibc::FEE_SEED], &solana_ibc::ID); + + // let receiver_token_account = + // get_associated_token_address(&solver.pubkey(), &dummy_token_mint); + + // // Build and send the transaction to call send_funds_to_user + // println!("\nSending funds to user"); + // let sig = program + // .request() + // .instruction(ComputeBudgetInstruction::set_compute_unit_limit( + // 1_000_000, + // )) + // .accounts(crate::accounts::SplTokenTransfer { + // intent: intent_state, + // auctioneer_state, + // solver: solver.pubkey(), + // auctioneer: auctioneer.pubkey(), + // token_in: None, + // token_out, + // auctioneer_token_in_account: None, + // solver_token_in_account: None, + // solver_token_out_account: solver_token_out_addr, + // user_token_out_account: user_token_out_addr, + // token_program: anchor_spl::token::ID, + // associated_token_program: anchor_spl::associated_token::ID, + // system_program: anchor_lang::solana_program::system_program::ID, + // ibc_program: Some(solana_ibc::ID), + // receiver: Some(user.pubkey()), + // storage: Some(storage), + // trie: Some(trie), + // chain: Some(chain), + // mint_authority: Some(mint_authority), + // token_mint: Some(dummy_token_mint), + // escrow_account: Some(escrow_account), + // receiver_token_account: Some(receiver_token_account), + // fee_collector: Some(fee_collector), + // }) + // .args(crate::instruction::SendFundsToUser { + // intent_id: intent_id.clone(), + // hashed_full_denom: Some(hashed_full_denom), + // // Solver out doesnt matter for this test + // solver_out: Some(Pubkey::new_unique().to_string()), + // }) + // .payer(solver.clone()) + // .signer(&*solver) + // .send_with_spinner_and_config(RpcSendTransactionConfig { + // skip_preflight: true, + // ..RpcSendTransactionConfig::default() + // })?; + // println!(" Signature: {sig}"); + + // // on receive funds + // let sig = program + // .request() + // .accounts(crate::accounts::ReceiveTransferContext { + // auctioneer_state, + // authority: auctioneer.pubkey(), + // escrow_token_account: token_in_escrow_addr, + // token_mint: token_in, + // solver_token_account: solver_token_in_addr, + // token_program: anchor_spl::token::ID, + // instruction: crate::solana_program::sysvar::instructions::ID, + // }) + // .args(crate::instruction::OnReceiveTransfer { memo: "".to_string() }) + // .payer(auctioneer.clone()) + // .signer(&*auctioneer) + // .send_with_spinner_and_config(RpcSendTransactionConfig { + // skip_preflight: true, + // ..RpcSendTransactionConfig::default() + // })?; + // println!(" Signature: {sig}"); + + // // on timeout (single domain) + // let sig = program + // .request() + // .accounts(crate::accounts::OnTimeout { + // caller: auctioneer.pubkey(), + // auctioneer_state, + // intent: intent_state, + // auctioneer: auctioneer.pubkey(), + // token_in: Some(token_in), + // user_token_account: Some(user_token_out_addr), + // escrow_token_account: Some(token_in_escrow_addr), + // token_program: anchor_spl::token::ID, + // associated_token_program: anchor_spl::associated_token::ID, + // system_program: anchor_lang::solana_program::system_program::ID, + // ibc_program: None, + // storage: None, + // trie: None, + // chain: None, + // mint_authority: None, + // token_mint: None, + // escrow_account: None, + // receiver_token_account: None, + // fee_collector: None, + // receiver: None, + // }) + // .args(crate::instruction::OnTimeout { intent_id: intent_id.clone() }) + // .payer(auctioneer.clone()) + // .signer(&*auctioneer) + // .send_with_spinner_and_config(RpcSendTransactionConfig::default())?; + // println!(" Signature: {sig}"); + + // // on timeout (cross domain) + // let sig = program + // .request() + // .accounts(crate::accounts::OnTimeout { + // caller: auctioneer.pubkey(), + // auctioneer_state, + // intent: intent_state, + // auctioneer: auctioneer.pubkey(), + // token_in: None, + // user_token_account: None, + // escrow_token_account: None, + // token_program: anchor_spl::token::ID, + // associated_token_program: anchor_spl::associated_token::ID, + // system_program: anchor_lang::solana_program::system_program::ID, + // ibc_program: Some(solana_ibc::ID), + // storage: Some(storage), + // trie: Some(trie), + // chain: Some(chain), + // mint_authority: Some(mint_authority), + // token_mint: Some(dummy_token_mint), + // escrow_account: Some(escrow_account), + // receiver_token_account: Some(receiver_token_account), + // fee_collector: Some(fee_collector), + // receiver: Some(user.pubkey()), + // }) + // .args(crate::instruction::OnTimeout { intent_id: intent_id.clone() }) + // .payer(auctioneer.clone()) + // .signer(&*auctioneer) + // .send_with_spinner_and_config(RpcSendTransactionConfig::default())?; + // println!(" Signature: {sig}"); Ok(()) }