Open hkirat opened 4 months ago
Functions need to be
can you assign this issue to me
use solana_program::{ account_info::{next_account_info, AccountInfo}, entrypoint, entrypoint::ProgramResult, msg, program_error::ProgramError, pubkey::Pubkey, };
entrypoint!(process_instruction);
fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], instruction_data: &[u8], ) -> ProgramResult { if instruction_data.is_empty() { msg!("No instruction provided"); return Err(ProgramError::InvalidInstructionData); }
let (instruction, rest) = instruction_data.split_first().ok_or(ProgramError::InvalidInstructionData)?;
match instruction {
0 => initiate_transfer(accounts, rest),
1 => revert_transfer(accounts),
2 => dispense_transfer(accounts),
_ => {
msg!("Invalid instruction");
Err(ProgramError::InvalidInstructionData)
}
}
}
fn initiate_transfer(accounts: &[AccountInfo], amount_data: &[u8]) -> ProgramResult { let account_iter = &mut accounts.iter(); let provider_account = next_account_info(account_iter)?; let receiver_account = next_account_info(account_iter)?; let escrow_account = next_account_info(account_iter)?;
let amount = u64::from_le_bytes(*array_ref![amount_data, 0, 8]);
// Ensure provider is a signer
if !provider_account.is_signer {
msg!("Provider account must be a signer");
return Err(ProgramError::MissingRequiredSignature);
}
// Ensure the escrow account has enough space
if escrow_account.data_len() < 65 {
msg!("Escrow account data length is insufficient");
return Err(ProgramError::InvalidAccountData);
}
// Transfer lamports from provider to escrow
provider_account.try_borrow_mut_lamports()?.checked_sub(amount)
.ok_or(ProgramError::InsufficientFunds)?;
escrow_account.try_borrow_mut_lamports()?.checked_add(amount)
.ok_or(ProgramError::InvalidAccountData)?;
// Store provider and receiver addresses in escrow account data
let mut escrow_data = escrow_account.try_borrow_mut_data()?;
escrow_data[0..32].copy_from_slice(&provider_account.key.to_bytes());
escrow_data[32..64].copy_from_slice(&receiver_account.key.to_bytes());
escrow_data[64] = 0; // Task not completed
Ok(())
}
fn revert_transfer(accounts: &[AccountInfo]) -> ProgramResult { let account_iter = &mut accounts.iter(); let provider_account = next_account_info(account_iter)?; let escrow_account = next_account_info(account_iter)?;
// Ensure provider is a signer
if !provider_account.is_signer {
msg!("Provider account must be a signer");
return Err(ProgramError::MissingRequiredSignature);
}
// Ensure the escrow account has enough space
if escrow_account.data_len() < 65 {
msg!("Escrow account data length is insufficient");
return Err(ProgramError::InvalidAccountData);
}
// Transfer lamports from escrow back to provider
let escrow_data = escrow_account.try_borrow_data()?;
let amount = provider_account.lamports().checked_add(escrow_account.lamports())
.ok_or(ProgramError::Overflow)?;
provider_account.try_borrow_mut_lamports()?.checked_add(escrow_account.lamports())
.ok_or(ProgramError::Overflow)?;
**escrow_account.try_borrow_mut_lamports()? = 0;
// Clear provider and receiver addresses from escrow account data
let mut escrow_data = escrow_account.try_borrow_mut_data()?;
escrow_data[0..64].fill(0);
Ok(())
}
fn dispense_transfer(accounts: &[AccountInfo]) -> ProgramResult { let account_iter = &mut accounts.iter(); let provider_account = next_account_info(account_iter)?; let escrow_account = next_account_info(account_iter)?; let treasury_account = next_account_info(account_iter)?;
// Ensure provider is a signer
if !provider_account.is_signer {
msg!("Provider account must be a signer");
return Err(ProgramError::MissingRequiredSignature);
}
// Ensure the escrow account has enough space
if escrow_account.data_len() < 65 {
msg!("Escrow account data length is insufficient");
return Err(ProgramError::InvalidAccountData);
}
// Calculate amount to dispense and transfer to receiver
let escrow_data = escrow_account.try_borrow_data()?;
let amount = escrow_account.lamports().checked_sub(escrow_account.lamports() / 20) // 5% for treasury
.ok_or(ProgramError::InsufficientFunds)?;
**escrow_account.try_borrow_mut_lamports()? = 0;
**treasury_account.try_borrow_mut_lamports()? += escrow_account.lamports() / 20;
**provider_account.try_borrow_mut_lamports()? += amount;
// Clear provider and receiver addresses from escrow account data
let mut escrow_data = escrow_account.try_borrow_mut_data()?;
escrow_data[0..64].fill(0);
Ok(())
}
In this code:
initiate_transfer is called to escrow the specified amount from the provider's account. It stores the provider and receiver addresses in the escrow account data. revert_transfer is called to revert the transfer if the task is not completed. It returns the escrowed amount from the escrow account to the provider's account. dispense_transfer is called to dispense the escrowed amount to the receiver's account after deducting 5% for the treasury. It transfers the amount to the receiver's account and sends 5% to the treasury account.
use anchor_lang::prelude::*;
declare_id!("Fg6PaFpoGXkYsidMpWFKtnpM7K6JZrTAmL5qXXCijMWd");
pub mod solana_escrow {
use super::*;
pub fn initiate_transfer(ctx: Context
pub fn revert_transfer(ctx: Context<RevertTransfer>) -> ProgramResult {
let escrow_account = &mut ctx.accounts.escrow_account;
let provider_account = &mut ctx.accounts.provider_account;
**provider_account.to_account_info().try_borrow_mut_lamports()? += escrow_account.amount;
**escrow_account.to_account_info().try_borrow_mut_lamports()? -= escrow_account.amount;
escrow_account.amount = 0;
Ok(())
}
pub fn dispense_transfer(ctx: Context<DispenseTransfer>) -> ProgramResult {
let escrow_account = &mut ctx.accounts.escrow_account;
let receiver_account = &mut ctx.accounts.receiver_account;
let treasury_account = &mut ctx.accounts.treasury_account;
let treasury_cut = (escrow_account.amount as f64 * 0.05) as u64;
let receiver_amount = escrow_account.amount - treasury_cut;
**receiver_account.to_account_info().try_borrow_mut_lamports()? += receiver_amount;
**treasury_account.to_account_info().try_borrow_mut_lamports()? += treasury_cut;
**escrow_account.to_account_info().try_borrow_mut_lamports()? -= escrow_account.amount;
escrow_account.amount = 0;
Ok(())
}
}
pub struct InitiateTransfer<'info> {
pub provider_account: Signer<'info>,
#[account(mut)]
pub escrow_account: Account<'info, EscrowAccount>,
}
pub struct RevertTransfer<'info> {
pub provider_account: Signer<'info>,
#[account(mut)]
pub escrow_account: Account<'info, EscrowAccount>,
}
pub struct DispenseTransfer<'info> {
pub escrow_account: Account<'info, EscrowAccount>,
#[account(mut)]
pub receiver_account: AccountInfo<'info>,
#[account(mut)]
pub treasury_account: AccountInfo<'info>,
}
pub struct EscrowAccount { pub amount: u64, }
A simple smart contract that takes
Needs to be done on solana