Description:
This program implements a secure deposit and withdrawal functionality for a Solana treasury account. Users can deposit SOL tokens and withdraw them with proper signature verification.
Installation:
- Set up an Anchor development environment: https://docs.anchor.xyz/
- Clone this repository:
git clone https://github.com/weichain/galactic-bridge-sol
- Install dependencies:
yarn install
- Run tests:
anchor test
Usage: See examples in tests/solana-treasury.ts
Depositing SOL:
-
Users can deposit SOL by calling the
deposit
function with the desired amount and their ICP address.Inputs:
-
Context ctx: Provides access to relevant accounts and program information.
- payer: This
Signer
account represents the party initiating the deposit and providing the funds. - treasury: This
SystemAccount
represents the account that will receive the deposited lamports. - system_program: This
Program
account represents the Solana system program, which provides functionalities like transferring lamports between accounts.
- payer: This
-
DepositData data: Contains the deposit details:
- amount: The amount of lamports to deposit (u64).
- address_icp: The ICP address to receive gSOL(String).
Event Emission:
-
Emit a
DepositEvent
after a successful deposit. -
This event provides information about the transaction to interested parties, enabling integration with other applications or monitoring systems.
Fields within DepositEvent:
- address_icp: This field stores the receiver's ICP address obtained from the
data.address_icp
input. - amount: This field holds the deposited amount (
transfer_amount
) transferred from the payer to the treasury.
- address_icp: This field stores the receiver's ICP address obtained from the
Outputs:
- Result<()>: Indicates success (Ok()) or an error (Err(DepositError)).
- DepositEvent: An emitted event containing:
- address_icp: The ICP address to receive gSol.
- amount: The deposited amount.
Algorithm Flow:
-
Validation:
- Checks if the payer is a signer. If not, returns
DepositError::PayerNotSigner
. - Verifies if the payer has enough lamports to cover the transfer. If not, returns
DepositError::PayerInsufficientAmount
.
- Checks if the payer is a signer. If not, returns
-
Transfer:
- Uses the
transfer
instruction from the system program to transfer lamports from the payer's account to the treasury account.
- Uses the
-
Event Emission:
- Emits a
DepositEvent
with the receiver's ICP address and the deposited amount.
- Emits a
-
Success:
- Returns
Ok(())
to signal successful deposit.
- Returns
-
Withdrawing SOL:
-
Users can withdraw SOL from the treasury by calling
withdraw
function providing a signed message containing the withdrawal amount, receiver Solana address, a valid signature, and a valid data hash.Inputs:
- Context ctx: Provides access to relevant accounts and program information.
- WithdrawData data: Contains data for withdrawal:
- message: A hashed message for verification (Vec).
- signature: A signature over the message ([u8; 64]).
- verify_data: Information for verification:
- address: The recipient's address (String).
- amount: The withdrawal amount in Ethereum format (u64).
Outputs:
- Result<()>: Indicates success (Ok()) or errors:
- WithdrawError: Treasury-related issues.
- ValidationError: Data or signature validation failures.
Algorithm Flow:
-
Validation:
- Checks if the treasury has enough lamports for the withdrawal.
- Calls
utils::verify
to verify:- Message hash matches the generated hash from verify_data.
- Signature validity using provided Ethereum public key.
-
Signer Seeds:
- Prepares seeds for treasury PDA (Program Derived Account).
-
Transfer:
- Uses
transfer
with signer seeds to transfer lamports from treasury to receiver.
- Uses
-
Success:
- Returns
Ok(())
if successful.
- Returns
Signature verification
-
This function
utils::verify
which is used inwithdraw
before transfering lamports, verifies the integrity and authenticity of a withdrawal request in a Solana program.Inputs:
eth_pubkey
: Ethereum public key which is hardcoded in the Treasury program, associated with the withdrawal request ([u8; 64]).msg
: The message bytes representing the withdrawal information (Vec).sig
: The signature over the message ([u8; 64]).msg_address
: The recipient's address for the withdrawal (String).msg_amount
: The withdrawal amount in Ethereum format (u64).
Outputs:
Result<()>
: Indicates success (Ok()) or error (Err(ValidationError)):InvalidDataHash
: The message hash doesn't match the data derived frommsg_address
andmsg_amount
.InvalidSignature
: The signature doesn't match the provided Ethereum public key.
Algorithm Flow:
- Message Construction:
- Creates a formatted string message containing
msg_address
andmsg_amount
.
- Creates a formatted string message containing
- Hashing:
- Calculates the hash of the constructed message.
- Data Hash Validation:
- Compares the provided message bytes (
msg
) with the hash of the constructed message. If they don't match, it throws anInvalidDataHash
error, indicating a mismatch between the signed data and the claimed withdrawal details.
- Compares the provided message bytes (
- Signature Verification:
- Attempts to recover the public key from the signature (
sig
) usingsolana_program::secp256k1_recover::secp256k1_recover
function. - If the recovered public key matches the pubkey embeded in the program, it signifies a valid signature.
- Attempts to recover the public key from the signature (
- Validation Result:
- If no match is found for the recovered public key and the pubkey embeded in the program, it throws an
InvalidSignature
error, indicating the signature doesn't correspond to the provided public key. - If data and signature verification are successful, the function returns
Ok(())
.
- If no match is found for the recovered public key and the pubkey embeded in the program, it throws an
Key Points:
- Used for cross-chain communication, specifically verifying Ethereum-related withdrawals on Solana.
- Ensures the integrity of the withdrawal request (message not tampered with) and authenticity (signature originates from the intended party).
- Employs
secp256k1_recover
for signature recovery with support for both recovery IDs. - Throws specific errors for data and signature verification failures.