From 84583fa1db1a90550198ef8346bc1b42ce314122 Mon Sep 17 00:00:00 2001 From: Priyanshu Mishra Date: Tue, 10 Sep 2024 12:03:44 +0530 Subject: [PATCH] add solana gateway doc --- .../solana-guides/README.mdx | 24 +++ .../solana-guides/_category_.json | 4 + .../solana-guides/args-accounts/README.md | 6 + .../args-accounts/_category_.json | 4 + .../args-accounts/packet_account.md | 203 ++++++++++++++++++ .../asm-implementation/README.md | 58 +++++ .../asm-implementation/_category_.json | 4 + .../solana-guides/iDapp-functions/README.md | 8 + .../iDapp-functions/_category_.json | 4 + .../solana-guides/iDapp-functions/i_ack.md | 41 ++++ .../iDapp-functions/i_receive.md | 41 ++++ .../solana-guides/iDapp-functions/i_send.md | 182 ++++++++++++++++ .../iDapp-functions/set_dapp_metadata.md | 52 +++++ 13 files changed, 631 insertions(+) create mode 100644 docs/develop/message-transfer-via-crosstalk/solana-guides/README.mdx create mode 100644 docs/develop/message-transfer-via-crosstalk/solana-guides/_category_.json create mode 100644 docs/develop/message-transfer-via-crosstalk/solana-guides/args-accounts/README.md create mode 100644 docs/develop/message-transfer-via-crosstalk/solana-guides/args-accounts/_category_.json create mode 100644 docs/develop/message-transfer-via-crosstalk/solana-guides/args-accounts/packet_account.md create mode 100644 docs/develop/message-transfer-via-crosstalk/solana-guides/asm-implementation/README.md create mode 100644 docs/develop/message-transfer-via-crosstalk/solana-guides/asm-implementation/_category_.json create mode 100644 docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/README.md create mode 100644 docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/_category_.json create mode 100644 docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/i_ack.md create mode 100644 docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/i_receive.md create mode 100644 docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/i_send.md create mode 100644 docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/set_dapp_metadata.md diff --git a/docs/develop/message-transfer-via-crosstalk/solana-guides/README.mdx b/docs/develop/message-transfer-via-crosstalk/solana-guides/README.mdx new file mode 100644 index 00000000..2dad0aad --- /dev/null +++ b/docs/develop/message-transfer-via-crosstalk/solana-guides/README.mdx @@ -0,0 +1,24 @@ +--- +title: Solana Guides +sidebar_position: 1 +--- + +import { + HomepageCard as Card, + HomepageSection as Section, +} from '../../../../src/components/HomepageComponents'; + +This section will cover how the crosschain framework can be used for Solana contracts to build iDapps. It provides the details around various functions and how they can be implemented using some sample contracts. + +
+ + +
\ No newline at end of file diff --git a/docs/develop/message-transfer-via-crosstalk/solana-guides/_category_.json b/docs/develop/message-transfer-via-crosstalk/solana-guides/_category_.json new file mode 100644 index 00000000..49b2183c --- /dev/null +++ b/docs/develop/message-transfer-via-crosstalk/solana-guides/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Solana Guides", + "position":5 +} diff --git a/docs/develop/message-transfer-via-crosstalk/solana-guides/args-accounts/README.md b/docs/develop/message-transfer-via-crosstalk/solana-guides/args-accounts/README.md new file mode 100644 index 00000000..8f5fce5b --- /dev/null +++ b/docs/develop/message-transfer-via-crosstalk/solana-guides/args-accounts/README.md @@ -0,0 +1,6 @@ +# Args Accounts + +The Args Accounts are used to store temporary function arguments, helping to avoid passing them directly into functions. This prevents reaching transaction limits and ensures the transaction is processed smoothly. + + + diff --git a/docs/develop/message-transfer-via-crosstalk/solana-guides/args-accounts/_category_.json b/docs/develop/message-transfer-via-crosstalk/solana-guides/args-accounts/_category_.json new file mode 100644 index 00000000..284fb4fc --- /dev/null +++ b/docs/develop/message-transfer-via-crosstalk/solana-guides/args-accounts/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Args Accounts", + "position": 1 +} \ No newline at end of file diff --git a/docs/develop/message-transfer-via-crosstalk/solana-guides/args-accounts/packet_account.md b/docs/develop/message-transfer-via-crosstalk/solana-guides/args-accounts/packet_account.md new file mode 100644 index 00000000..723936ad --- /dev/null +++ b/docs/develop/message-transfer-via-crosstalk/solana-guides/args-accounts/packet_account.md @@ -0,0 +1,203 @@ +--- +title: packet_account +sidebar_position: 1 +--- + +## Packet Account + +The Packet Account is used to store request packet information or messages that need to be delivered to the `i_receive` or `i_ack` functions of the Gateway contract. + + +### Packet Account Structure: + +The Packet Account is serialized as follows: + +1. `[0..32] - Creator`: The first 32 bytes represent the account creator. +2. `[33] - Blocked Status`: The 33rd byte indicates whether the account is blocked or not. +If the account is blocked, it can only be deleted. +3. `[34..37] - Packet Length`: Bytes 34 to 37 contain the length of the packet in little-endian format. +4. `[38..(37 + packet_length)] - Packet Data`: Starting from byte 38, the packet data is stored. The length of the data is determined by the packet_length field. + +### Prefix: + +```rust +const PACKET_SEED_PREFIX: &[u8] = b"PA_"; +``` + +### Instructions: + + +1. `initialize_packet_account` + +```rust +pub fn initialize_packet_account( + ctx: Context, + seed: Vec, + packet: Option>, +) -> Result<()> +``` + +##### Description: +* Initializes a new Packet Account. The seed is used to generate a unique PDA (Program Derived Address), and an optional packet can be included. If no packet is passed, the packet length is set to 0. + +##### Cost: +* Approximately `0.07216128 SOL`, which can be reclaimed upon deletion of the account. Only the creator of the account can delete it. + +##### Parameters: + +* `seed`: A unique identifier to generate the PDA. +* `packet`: Optional packet data. If None, the packet length is 0. + +##### Account Context: + +```rust +#[derive(Accounts)] +#[instruction(seed: Vec)] +pub struct InitializePacketAccount<'info> { + #[account( + init, + payer=signer, + seeds=[ + PACKET_SEED_PREFIX, + &seed + ], + bump, + space= PacketAccount::SIZE + )] + pub packet_account: AccountLoader<'info, PacketAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} +``` + +
+
+
+ + +2. `append_packet_account` + +```rust +pub fn append_packet_account( + ctx: Context, + seed: Vec, + packet: Vec, +) -> Result<()> +``` + +##### Description: +* Appends additional data to an existing Packet Account. The seed used during initialization must be provided to locate the correct account. + +##### Parameters: + +* `seed`: The same seed used when initializing the Packet Account. +* `packet`: The data to append to the existing packet account. + +##### Account Context: + +```rust +#[derive(Accounts)] +#[instruction(seed: Vec)] +pub struct UpdatePacketAccount<'info> { + #[account( + mut, + seeds=[PACKET_SEED_PREFIX, &seed], + bump, + )] + pub packet_account: AccountLoader<'info, PacketAccount>, + #[account()] + pub signer: Signer<'info>, +} +``` +
+
+
+ +3. `update_packet_account` + +```rust +pub fn update_packet_account( + ctx: Context, + seed: Vec, + slice: Vec, + from: u64, + to: u64, +) -> Result<()> +``` + +##### Description: +* Updates a portion of the packet data in an existing Packet Account, replacing the data from index `from` to `to`. + + +##### Parameters: + +* `seed`: The same seed used during initialization. +* `slice`: The data to replace the existing packet content. +* `from`: The starting index of the data to replace. +* `to`: The ending index of the data to replace. + +
+
+
+ + +4. `update_packet_creator` + +```rust +pub fn update_packet_creator( + ctx: Context, + seed: Vec, + new_owner: Pubkey, +) -> Result<()> +``` + +##### Description: +* Allows the creator of the Packet Account to transfer ownership to a new public key (`new_owner`). + +##### Parameters: +* `seed`: The same seed used during initialization. +* `new_owner`: The new owner (`public key`) of the packet. + +
+
+
+ +5. `delete_packet_account` + +```rust +pub fn delete_packet_account( + _ctx: Context, + _seed: Vec +) -> Result<()> +``` + +##### Description: +* Deletes the Packet Account and refunds the remaining SOL back to the signer. Only the original creator of the account can perform this operation. + +##### Parameters: +* `seed`: The same seed used during initialization. + + +##### Account Context: + +```rust +#[derive(Accounts)] +#[instruction(seed: Vec)] +pub struct DeletePacketAccount<'info> { + #[account( + mut, + seeds=[PACKET_SEED_PREFIX, &seed], + bump, + constraint = packet_account.load()?.get_creator() == signer.key() @GatewayError::OnlyCreator, + close = signer + )] + pub packet_account: AccountLoader<'info, PacketAccount>, + #[account(mut)] + pub signer: Signer<'info>, +} +``` +
+
+ + diff --git a/docs/develop/message-transfer-via-crosstalk/solana-guides/asm-implementation/README.md b/docs/develop/message-transfer-via-crosstalk/solana-guides/asm-implementation/README.md new file mode 100644 index 00000000..1a2bb290 --- /dev/null +++ b/docs/develop/message-transfer-via-crosstalk/solana-guides/asm-implementation/README.md @@ -0,0 +1,58 @@ +--- +title: ASM Implementation +sidebar_position: 1 +--- + +:::info +To understand how Router ASM works, refer to this [link](../../message-transfer-via-crosstalk/key-concepts/additional-security-modules#how-does-an-asm-work). +::: + +The function `verify_cross_chain_request` enhances security for a specific cross-chain flow. + +When a request is received on the destination chain, the `verify_cross_chain_request` function is invoked on the specified ASM (Application Security Module) address before executing the user's contract calls. The ASM can return either `true` or `false` to instantly validate or invalidate the request. If further time is needed for validation, the ASM can revert the request. + +If the function returns `true`, the execution of the user contract calls will proceed. If it returns `false`, the contract calls will be skipped. Should the ASM implementation revert the request, the transaction will be rolled back, and no state changes will occur on the Gateway. + +The ASM module can continue to revert requests until it can confidently validate or invalidate them. This ensures that application-level validation is completed before any cross-chain request is executed on the Gateway contract and sent to the destination contract. + + +```javascript + pub fn verify_cross_chain_request( + ctx: Context, + request_identifier: u128, + request_timestamp: u128, + request_sender: String, + src_chain_id: String, + handler_program_pub_key: Pubkey, + handler_account_pub_key: Pubkey, +) -> Result +``` + +In this function selector, there are 6 arguments. Within this function, any possible business logic or validation can be added using these arguments. Each argument has its own purpose in the `verify_cross_chain_request` request: + +##### Parameters: + +* `request_identifier`: A unique identifier of the request. It is added by the source chain's Gateway contract. +* `request_timestamp`: Timestamp when a request is added/verified on the Router Chain. +* `request_sender`: The address of the application's contract on the source chain, represented as a string. +* `src_chain_id`: The chain ID of the src chain, in string format. +* `handler_program_pub_key`: The program ID for which this request is intended. +* `handler_account_pub_key`: The program-derived account for the current handler program. + +#### Account Context +```rust +#[derive(Accounts)] +pub struct VerifyCrossChainRequest<'info> { + //CHECK: asm can have different storage structure, asm have to validate account + #[account(mut)] + pub asm_account: UncheckedAccount<'info>, + // it is passed so that asm contract can validate if it is signed by authorised program id + #[account()] + pub gateway_authority: Signer<'info>, + pub system_program: Program<'info, System>, + //NOTE: all remaining account will be passed as well +} +``` + +`Security Note:` Since this function can be called from the Gateway contract only, it must validate `gateway_authority` with expected signer. + diff --git a/docs/develop/message-transfer-via-crosstalk/solana-guides/asm-implementation/_category_.json b/docs/develop/message-transfer-via-crosstalk/solana-guides/asm-implementation/_category_.json new file mode 100644 index 00000000..49bd952e --- /dev/null +++ b/docs/develop/message-transfer-via-crosstalk/solana-guides/asm-implementation/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "ASM Implementation", + "position": 4 +} \ No newline at end of file diff --git a/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/README.md b/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/README.md new file mode 100644 index 00000000..ed7e5218 --- /dev/null +++ b/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/README.md @@ -0,0 +1,8 @@ +# Solana iDapp Functions + +Cross-chain message transmission on the Solana chain is enabled through the `i_send` function in Router's Gateway contract. When initiating a cross-chain request, developers can invoke this function, passing the required parameters along with the payload that needs to be transferred from the source chain to the destination chain. + +To ensure successful cross-chain communication, Solana iDapp developers must also implement the following essential functions within their contracts: +1. `i_receive`: This function must be included on the destination chain to handle incoming cross-chain requests. +2. `i_ack`: Implement this function to process acknowledgment of requests on the source chain, particularly when cross-chain acknowledgment is required. +3. `set_dapp_metadata`: This function is necessary to designate a fee_payer for executing cross-chain requests. Without setting this, requests will remain in a blocked state on the Router Chain. diff --git a/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/_category_.json b/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/_category_.json new file mode 100644 index 00000000..f2e89c24 --- /dev/null +++ b/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "iDapp Functions", + "position": 2 +} \ No newline at end of file diff --git a/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/i_ack.md b/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/i_ack.md new file mode 100644 index 00000000..d476446c --- /dev/null +++ b/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/i_ack.md @@ -0,0 +1,41 @@ +--- +title: i_ack +sidebar_position: 4 +--- + +After the `i_receive` function is executed, an acknowledgment is generated by Router's destination chain Gateway contract, indicating whether the call was successful. The i_ack function must be implemented in your contract with the following structure: + +```rust +pub fn i_ack( + ctx: Context, + request_identifier: u128, + exec_flag: bool, +) -> Result> +``` + +#### Parameters: +* `request_identifier`: This is the same nonce received when calling the `i_send` function on the source chain's Gateway contract. It helps map the acknowledgment to the corresponding request. +* `src_chain_id`: A boolean value indicating the execution status of the request on the destination chain. + +#### Account Context +```rust +#[derive(Accounts)] +pub struct IAck<'info> { + //CHECK: dapp can have different storage structure, dapp have to validate account + #[account(mut)] + pub dapp_account: UncheckedAccount<'info>, + #[account()] + pub packet_account: AccountLoader<'info, PacketAccount>, + #[account()] + pub gateway_authority: Signer<'info>, + pub system_program: Program<'info, System>, +} +``` + +#### Account Info: +* `packet_account`: Contains the exec data which is the data in bytes that provides the abi-encoded return value from the `i_receive` call on the destination chain. Based on the application's requirement, this data can be decoded and processed on the source chain. +* `gateway_authority`: The authorized signer by the Gateway contract to ensure the request is valid. + +:::caution +Currently, `i_ack` does not support dynamically passing additional accounts beyond those explicitly listed in the IAck context. +::: diff --git a/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/i_receive.md b/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/i_receive.md new file mode 100644 index 00000000..4d10e60a --- /dev/null +++ b/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/i_receive.md @@ -0,0 +1,41 @@ +--- +title: i_receive +sidebar_position: 3 +--- + +The cross-chain request initiated from the source chain will deliver the payload to the destination contract address specified in the `contractCalls` parameter. On the destination contract, a function must be implemented to handle this payload: + +```rust +pub fn i_receive( + ctx: Context, + request_sender: String, + src_chain_id: String, +) -> Result> +``` + +#### Parameters: +* `request_sender`: The contract that initiated the request from the source chain. +* `src_chain_id`: The source chain id from where the cross-chain request originated. + +#### Account Context +```rust +#[derive(Accounts)] +pub struct DappIReceive<'info> { + //CHECK: dapp can have different storage structure, dapp have to validate account + #[account(mut)] + pub dapp_account: UncheckedAccount<'info>, + #[account()] + pub packet_account: AccountLoader<'info, PacketAccount>, + #[account()] + pub gateway_authority: Signer<'info>, + pub system_program: Program<'info, System>, +} +``` + +#### Account Info: +* `packet_account`: Contains the payload being sent from the source chain. +* `gateway_authority`: The authorized signer by the Gateway contract to ensure the request is valid. + +:::caution +It is mandatory to include this function in your contract on the destination chain; otherwise, the request will fail. +::: diff --git a/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/i_send.md b/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/i_send.md new file mode 100644 index 00000000..1e144f51 --- /dev/null +++ b/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/i_send.md @@ -0,0 +1,182 @@ +--- +title: i_send +sidebar_position: 2 +--- + +The `i_send` function is used to send a cross-chain message or request. Before calling i_send, users must initialize a Request Packet Account and append the necessary message to it. The format of the request packet should follow this structure: + +
+Making Request To Solana + +The destination contract stores account information in the following order, encoded as hex: +* `[0..32]`: Destination Program ID +* `[32..64]`: Destination Program Account +* `[64..]`: All remaining accounts in order + +
+ +### Request Packet Structure: + +* [0..4]: Length of the destination contract's UTF-8 bytes (4 bytes) +* [4..4 + utf_dst_Contract_length]: UTF-8 encoded destination contract (variable length) +* [4 + utf_dst_Contract_length..8 + utf_dst_Contract_length]: Destination payload data length (4 bytes) +* [8 + utf_dst_Contract_length..8 + utf_dst_Contract_length + dst_payload_length]: Destination payload data (variable length) + +### Prefix: + +```rust +const PACKET_SEED_PREFIX: &[u8] = b"PA_"; +pub const GATEWAY_ACCOUNT: &[u8] = b"gateway_account"; +pub const DAPP_ACCOUNT: &[u8] = b"dapp_account"; +``` + +```rust +pub fn i_send( + ctx: Context, + packet_seed: Vec, + version: u128, + route_amount: u64, + route_recipient: String, + dest_chain_id: String, + request_metadata: Vec, +) -> Result +``` + +##### Parameters: + +* `packet_seed`: The seed for the Request Packet Account, used to generate a Program Derived Address (PDA) for storing the request packet. This must be initialized prior to calling i_send. +* `version`: The current version of the Gateway contract, which can be obtained by reading the Gateway Account. Versions may change when the encoding of request_metadata changes. However, previous versions are still supported for backward compatibility with iDapps. +* `route_amount`: The amount of ROUTE tokens to be transferred to the destination chain. +Note: If a non-zero route_amount is provided, additional accounts like signer_associate_account, mint, associated_token_program, and token_program (optional) are required. +* route_recipient: The recipient's address on the destination chain to receive the ROUTE tokens. +If the ROUTE token transfer is not required, this parameter can be set to an empty string (""). +* `dest_chain_id`: The chain ID of the destination chain, in string format. +* `request_metadata`: A byte-encoded string that includes various cross-chain request parameters, avoiding the need for on-chain encoding. This metadata is dependent on the destination chain ID and includes the following information: + +###### Request Metadata Parameters: + +1. `dest_gas_limit`: Gas limit for executing the request on the destination chain. +2. `dest_gas_price`: Gas price of the destination chain. Can be set to 0 if you want the Router Chain to estimate the gas price. +3. `ack_gas_limit`: Gas limit for executing the acknowledgment on the source chain. +4. `ack_gas_price`: Gas price of the source chain. Set to 0 to have it estimated by the Router Chain. +5. `relayer_fees`: Fee to be paid to the Router Chain relayers. If set too low, it will be automatically adjusted by the Router Chain. Setting 0 will use the minimum fee required. +6. `ack_type`: Defines the type of acknowledgment: + * 0: No acknowledgment + * 1: Acknowledgment only on successful execution. + * 2: Acknowledgment only on failure. + * 3: Acknowledgment regardless of success or failure. +7. `is_read_call`: Set to `true` if the request is a read-only call on the destination chain. +8. `asm_address`: The address of the ASM Module on the destination chain for added security. + +
+Metadata Construction + +You can construct the request_metadata either in Rust or in JavaScript/TypeScript using the provided functions. + +###### Rust Implementation: + +```rust +fn get_request_metadata( + dest_gas_limit: u64, + dest_gas_price: u64, + ack_gas_limit: u64, + ack_gas_price: u64, + relayer_fees: U128, + ack_type: u8, + is_read_call: bool, + asm_address: String +) -> Vec { + let mut request_metadata: Vec = vec![]; + request_metadata.append(&mut dest_gas_limit.to_be_bytes().to_vec()); + request_metadata.append(&mut dest_gas_price.to_be_bytes().to_vec()); + request_metadata.append(&mut ack_gas_limit.to_be_bytes().to_vec()); + request_metadata.append(&mut ack_gas_price.to_be_bytes().to_vec()); + request_metadata.append(&mut u128::from(relayer_fees).to_be_bytes().to_vec()); + request_metadata.append(&mut ack_type.to_be_bytes().to_vec()); + request_metadata.append(&mut vec![if is_read_call { 1 } else { 0 }]); + request_metadata.append(&mut asm_address.as_bytes().to_vec()); + + request_metadata +} +``` + +###### JavaScript/TypeScript Implementation: + +```javascript +function getRequestMetadata( + destGasLimit: number, + destGasPrice: number, + ackGasLimit: number, + ackGasPrice: number, + relayerFees: string, + ackType: number, + isReadCall: boolean, + asmAddress: string +): string { + return ethers.utils.solidityPack( + [ + 'uint64', + 'uint64', + 'uint64', + 'uint64', + 'uint128', + 'uint8', + 'bool', + 'string', + ], + [ + destGasLimit, + destGasPrice, + ackGasLimit, + ackGasPrice, + relayerFees, + ackType, + isReadCall, + asmAddress, + ] + ); +} +``` + +
+ + +##### Account Context: + +```rust +#[event_cpi] +#[derive(Accounts)] +#[instruction(packet_seed: Vec)] +pub struct ISend<'info> { + #[account(mut, seeds = [GATEWAY_ACCOUNT], bump = gateway_account.gateway_account_bump)] + pub gateway_account: Account<'info, GatewayAccount>, + #[account(mut, seeds = [PACKET_SEED_PREFIX, &packet_seed], bump)] + pub request_packet: AccountLoader<'info, PacketAccount>, + #[account()] + pub dapp_signer_account: Signer<'info>, + #[account(seeds = [DAPP_ACCOUNT, dapp_signer_account.key.as_ref()], bump)] + pub dapp_account: Account<'info, DappAccount>, + #[account(mut)] + pub signer: Signer<'info>, + #[account( + init_if_needed, + associated_token::mint = mint, + associated_token::authority = signer, + payer = signer, + )] + pub signer_associate_account: Option>>, + #[account( + mut, + constraint = gateway_account.route_token == mint.key() + )] + pub mint: Option>>, + pub associated_token_program: Option>, + pub token_program: Option>, + pub system_program: Program<'info, System>, +} +``` + +:::caution +Once the message is delivered on the destination chain, the user can delete the Request Packet Account. It can also be deleted before message delivery, but this will invalidate the request. +::: + diff --git a/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/set_dapp_metadata.md b/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/set_dapp_metadata.md new file mode 100644 index 00000000..447483a3 --- /dev/null +++ b/docs/develop/message-transfer-via-crosstalk/solana-guides/iDapp-functions/set_dapp_metadata.md @@ -0,0 +1,52 @@ +--- +title: set_dapp_metadata +sidebar_position: 1 +--- + +* To facilitate cross-chain transactions, it is necessary to cover the fees on the Router Chain. This is achieved using the set_dapp_metadata function available in the Gateway contracts. +* Once the `fee_payer_address` is set, the designated fee payer must approve the request to act as the fee payer on the Router Chain. Without this approval, dApps will not be able to execute any cross-chain transactions. +* It's important to note that any fee refunds resulting from these transactions will be credited back to the dApp's `fee_payer_address` on the Router Chain. + +### Prefix: + +```rust +pub const GATEWAY_ACCOUNT: &[u8] = b"gateway_account"; +pub const DAPP_ACCOUNT: &[u8] = b"dapp_account"; +``` + +```rust +pub fn set_dapp_metadata( + ctx: Context, + fee_payer_address: String, + program_id: Pubkey, + program_account_id: Pubkey, +) -> Result<()> +``` + +##### Parameters: + +* `fee_payer_address`: The account responsible for covering the transaction fees for any cross-chain requests originating from the dApp. +* `program_id`: The dapp program id for which set_dapp_metadata is done. +* `program_account_id`: The dapp program account. + + +#### Account Context: +```rust +#[event_cpi] +#[derive(Accounts)] +pub struct SetDappMetadata<'info> { + #[account(mut, seeds = [GATEWAY_ACCOUNT], bump = gateway_account.gateway_account_bump)] + pub gateway_account: Account<'info, GatewayAccount>, + #[account()] + pub dapp_signer_account: Signer<'info>, + #[account(init_if_needed, seeds = [DAPP_ACCOUNT, dapp_signer_account.key.as_ref()], bump, payer = fee_payer_account, space = DISCRIMINATOR_SIZE + DappAccount::INIT_SPACE)] + pub dapp_account: Account<'info, DappAccount>, + #[account(mut)] + pub fee_payer_account: Signer<'info>, + pub system_program: Program<'info, System>, +} +``` + +:::caution +Without creating dApp accounts via the set_dapp_metadata function, it is not possible to make an i_send call. +:::