Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace pack with Borsh #1

Merged
merged 1 commit into from
Jul 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions program/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ edition = "2018"

[dependencies]
solana-program = "1.6.0"
byteorder = "1"
spl-token = { version = "3.1.0", features = ["no-entrypoint"]}
spl-associated-token-account = { version = "1.0.2", features = ["no-entrypoint"]}
num-derive = "0.3"
num-traits = "0.2"
thiserror = "1"
arrayref = "0.3.6"
borsh = "0.8.1"


[features]
Expand Down
204 changes: 37 additions & 167 deletions program/src/account.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
use crate::error::TreasuryError;
use arrayref::{array_mut_ref, array_ref};
use arrayref::{array_refs, mut_array_refs};
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::account_info::AccountInfo;
use solana_program::entrypoint::ProgramResult;
use solana_program::program::invoke_signed;
use solana_program::msg;
use solana_program::program_error::ProgramError;
use solana_program::program_pack::Pack;
use solana_program::pubkey::Pubkey;
use solana_program::pubkey::MAX_SEED_LEN;
use solana_program::system_instruction;
use solana_program::{
msg,
program_pack::{Pack, Sealed},
};
use spl_token::state::{Account as SPLAccount, Mint};

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[derive(Clone, Copy, Debug, Default, PartialEq, BorshSerialize, BorshDeserialize)]
pub struct Settings {
pub token: Pubkey,
pub fee_recipient: Pubkey,
Expand All @@ -24,8 +18,6 @@ pub struct Settings {
pub launch_fee_zoints: u64,
}

impl Sealed for Settings {}

impl Settings {
pub fn program_address(program_id: &Pubkey) -> (Pubkey, u8) {
Pubkey::find_program_address(&[b"settings"], program_id)
Expand All @@ -40,28 +32,6 @@ impl Settings {
Ok(seed)
}

pub fn create_account<'a>(
funder_info: &AccountInfo<'a>,
settings_info: &AccountInfo<'a>,
rent: solana_program::rent::Rent,
program_id: &Pubkey,
) -> ProgramResult {
let seed = Settings::verify_program_key(settings_info.key, program_id)?;
let lamports = rent.minimum_balance(Settings::LEN);
let space = Settings::LEN as u64;
invoke_signed(
&system_instruction::create_account(
funder_info.key,
settings_info.key,
lamports,
space,
program_id,
),
&[funder_info.clone(), settings_info.clone()],
&[&[b"settings", &[seed]]],
)
}

pub fn verify_fee_recipient(&self, key: &Pubkey) -> Result<(), ProgramError> {
match self.fee_recipient == *key {
true => Ok(()),
Expand Down Expand Up @@ -110,51 +80,12 @@ impl Settings {
}
}

impl Pack for Settings {
const LEN: usize = 32 + 32 + 32 + 8 + 8;
fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError> {
let src = array_ref![src, 0, Settings::LEN];
let (token, fee_recipient, price_authority, launch_fee_user, launch_fee_zoints) =
array_refs![src, 32, 32, 32, 8, 8];
let token = Pubkey::new(token);
let fee_recipient = Pubkey::new(fee_recipient);
let price_authority = Pubkey::new(price_authority);
let launch_fee_user = u64::from_le_bytes(*launch_fee_user);
let launch_fee_zoints = u64::from_le_bytes(*launch_fee_zoints);
Ok(Settings {
token,
fee_recipient,
price_authority,
launch_fee_user,
launch_fee_zoints,
})
}

fn pack_into_slice(&self, dst: &mut [u8]) {
let dst = array_mut_ref![dst, 0, Settings::LEN];
let (
token_dst,
fee_recipient_dst,
price_authority_dst,
launch_fee_user_dst,
launch_fee_zoints_dst,
) = mut_array_refs![dst, 32, 32, 32, 8, 8];
*token_dst = self.token.to_bytes();
*fee_recipient_dst = self.fee_recipient.to_bytes();
*price_authority_dst = self.price_authority.to_bytes();
*launch_fee_user_dst = self.launch_fee_user.to_le_bytes();
*launch_fee_zoints_dst = self.launch_fee_zoints.to_le_bytes();
}
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[derive(Clone, Copy, Debug, Default, PartialEq, BorshSerialize, BorshDeserialize)]
pub struct UserTreasury {
pub authority: Pubkey,
}

impl Sealed for UserTreasury {}

impl UserTreasury {
pub fn program_address(user: &Pubkey, program_id: &Pubkey) -> (Pubkey, u8) {
Pubkey::find_program_address(&[b"user", &user.to_bytes()], program_id)
Expand All @@ -172,61 +103,14 @@ impl UserTreasury {
}
Ok(seed)
}

pub fn create_account<'a>(
funder_info: &AccountInfo<'a>,
treasury_info: &AccountInfo<'a>,
creator_info: &AccountInfo<'a>,
rent: solana_program::rent::Rent,
program_id: &Pubkey,
) -> ProgramResult {
let seed =
UserTreasury::verify_program_key(treasury_info.key, creator_info.key, program_id)?;
let lamports = rent.minimum_balance(UserTreasury::LEN);
let space = UserTreasury::LEN as u64;
invoke_signed(
&system_instruction::create_account(
funder_info.key,
treasury_info.key,
lamports,
space,
program_id,
),
&[funder_info.clone(), treasury_info.clone()],
&[&[b"user", &creator_info.key.to_bytes(), &[seed]]],
)?;

let user_treasury = Self {
authority: *creator_info.key,
};
Self::pack(user_treasury, &mut treasury_info.data.borrow_mut())
}
}

impl Pack for UserTreasury {
const LEN: usize = 32;
fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError> {
let src = array_ref![src, 0, UserTreasury::LEN];

let authority = Pubkey::new(src);

Ok(UserTreasury { authority })
}

fn pack_into_slice(&self, dst: &mut [u8]) {
let authority_dst = array_mut_ref![dst, 0, UserTreasury::LEN];
*authority_dst = self.authority.to_bytes();
}
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[derive(Clone, Copy, Debug, Default, PartialEq, BorshDeserialize, BorshSerialize)]
pub struct ZointsTreasury {
pub authority: Pubkey,
}

impl Sealed for ZointsTreasury {}

impl ZointsTreasury {
pub fn program_address(name: &Vec<u8>, program_id: &Pubkey) -> (Pubkey, u8) {
Pubkey::find_program_address(&[b"zoints", name], program_id)
Expand Down Expand Up @@ -265,51 +149,6 @@ impl ZointsTreasury {
false => Err(TreasuryError::ZointsTreasuryNameInvalidCharacters.into()),
}
}

pub fn create_account<'a>(
funder_info: &AccountInfo<'a>,
treasury_info: &AccountInfo<'a>,
name: &Vec<u8>,
authority_info: &AccountInfo<'a>,
rent: solana_program::rent::Rent,
program_id: &Pubkey,
) -> ProgramResult {
let seed = ZointsTreasury::verify_program_key(treasury_info.key, name, program_id)?;
let lamports = rent.minimum_balance(ZointsTreasury::LEN);
let space = ZointsTreasury::LEN as u64;
invoke_signed(
&system_instruction::create_account(
funder_info.key,
treasury_info.key,
lamports,
space,
program_id,
),
&[funder_info.clone(), treasury_info.clone()],
&[&[b"zoints", name, &[seed]]],
)?;

let zoints_treasury = Self {
authority: *authority_info.key,
};
Self::pack(zoints_treasury, &mut treasury_info.data.borrow_mut())
}
}

impl Pack for ZointsTreasury {
const LEN: usize = 32;
fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError> {
let src = array_ref![src, 0, ZointsTreasury::LEN];

let authority = Pubkey::new(src);

Ok(ZointsTreasury { authority })
}

fn pack_into_slice(&self, dst: &mut [u8]) {
let authority_dst = array_mut_ref![dst, 0, ZointsTreasury::LEN];
*authority_dst = self.authority.to_bytes();
}
}

#[cfg(test)]
Expand Down Expand Up @@ -355,4 +194,35 @@ mod tests {
cast_error(TreasuryError::ZointsTreasuryNameInvalidCharacters)
);
}

#[test]
pub fn test_serialize_accounts() {
let settings = Settings {
token: Pubkey::new_unique(),
fee_recipient: Pubkey::new_unique(),
price_authority: Pubkey::new_unique(),
launch_fee_user: 9238478234,
launch_fee_zoints: 1239718515,
};
let settings_data = settings.try_to_vec().unwrap();
assert_eq!(settings, Settings::try_from_slice(&settings_data).unwrap());

let user_treasury = UserTreasury {
authority: Pubkey::new_unique(),
};
let user_treasury_data = user_treasury.try_to_vec().unwrap();
assert_eq!(
user_treasury,
UserTreasury::try_from_slice(&user_treasury_data).unwrap()
);

let zoints_treasury = ZointsTreasury {
authority: Pubkey::new_unique(),
};
let zoints_treasury_data = zoints_treasury.try_to_vec().unwrap();
assert_eq!(
zoints_treasury,
ZointsTreasury::try_from_slice(&zoints_treasury_data).unwrap()
);
}
}
10 changes: 9 additions & 1 deletion program/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use num_derive::FromPrimitive;
use solana_program::{decode_error::DecodeError, program_error::ProgramError};
use solana_program::{
decode_error::DecodeError, msg, program_error::PrintProgramError, program_error::ProgramError,
};
use thiserror::Error;

#[derive(Debug, Clone, PartialEq, Eq, Error, FromPrimitive)]
Expand Down Expand Up @@ -84,3 +86,9 @@ impl<T> DecodeError<T> for TreasuryError {
"TreasuryError"
}
}

impl PrintProgramError for TreasuryError {
fn print<E>(&self) {
msg!("TREASURY-ERROR: {}", &self.to_string());
}
}
Loading