implement withdraw without test
This commit is contained in:
parent
7eca995088
commit
88303c8545
|
@ -14,17 +14,14 @@ pub const PAYMENT_AMOUNT: u64 = 10;
|
|||
/// Instructions supported by the program
|
||||
#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, BorshSchema, PartialEq)]
|
||||
pub enum Instruction {
|
||||
/// Initializes a new Aggregator
|
||||
Initialize {
|
||||
config: AggregatorConfig,
|
||||
},
|
||||
|
||||
/// Add an oracle
|
||||
AddOracle {
|
||||
description: [u8; 32],
|
||||
},
|
||||
|
||||
/// Remove an oracle
|
||||
RemoveOracle,
|
||||
|
||||
Submit {
|
||||
|
@ -32,19 +29,8 @@ pub enum Instruction {
|
|||
value: u64,
|
||||
},
|
||||
|
||||
/// Oracle withdraw token
|
||||
///
|
||||
/// Accounts expected by this instruction:
|
||||
/// 0. `[writable]` The aggregator (key).
|
||||
/// 1. `[writable]` The faucet (which token transfer from)
|
||||
/// 2. `[writable]` The recevier (which token withdraw to)
|
||||
/// 3. `[]` SPL Token program id
|
||||
/// 4. `[]` The faucet owner
|
||||
/// 5. `[signer, writable]` The oracle's authority.
|
||||
Withdraw {
|
||||
/// withdraw amount
|
||||
amount: u64,
|
||||
/// program account nonced seed
|
||||
seed: [u8; 32],
|
||||
// FIXME: why 32 bytes seed? could be a vec?
|
||||
faucet_owner_seed: [u8; 32],
|
||||
},
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
//! An Flux Aggregator program for the Solana blockchain
|
||||
|
||||
|
||||
|
||||
pub mod borsh_state;
|
||||
pub mod borsh_utils;
|
||||
pub mod error;
|
||||
|
@ -14,9 +12,6 @@ pub mod state;
|
|||
#[cfg(not(feature = "no-entrypoint"))]
|
||||
pub mod entrypoint;
|
||||
|
||||
|
||||
|
||||
|
||||
/// Get median value from the aggregator account
|
||||
// pub fn get_median(aggregator_info: &AccountInfo) -> Result<u64, ProgramError> {
|
||||
// let aggregator = Aggregator::unpack_unchecked(&aggregator_info.data.borrow())?;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use crate::{
|
||||
error::Error,
|
||||
instruction::Instruction,
|
||||
state::{Aggregator, AggregatorConfig, Oracle, Round},
|
||||
state::{Aggregator, AggregatorConfig, Authority, Oracle, Round},
|
||||
};
|
||||
|
||||
use solana_program::{
|
||||
|
@ -77,14 +77,8 @@ struct AddOracleContext<'a> {
|
|||
impl<'a> AddOracleContext<'a> {
|
||||
fn process(&self) -> ProgramResult {
|
||||
// Note: there can in fact be more oracles than max_submissions
|
||||
if !self.aggregator_owner.is_signer {
|
||||
return Err(ProgramError::MissingRequiredSignature);
|
||||
}
|
||||
|
||||
let aggregator = Aggregator::load_initialized(self.aggregator)?;
|
||||
if aggregator.owner != self.aggregator_owner.key.to_bytes() {
|
||||
return Err(Error::OwnerMismatch)?;
|
||||
}
|
||||
aggregator.authorize(self.aggregator_owner)?;
|
||||
|
||||
let mut oracle = Oracle::init_uninitialized(self.oracle)?;
|
||||
oracle.is_initialized = true;
|
||||
|
@ -105,14 +99,8 @@ struct RemoveOracleContext<'a> {
|
|||
|
||||
impl<'a> RemoveOracleContext<'a> {
|
||||
fn process(&self) -> ProgramResult {
|
||||
if !self.aggregator_owner.is_signer {
|
||||
return Err(ProgramError::MissingRequiredSignature);
|
||||
}
|
||||
|
||||
let aggregator = Aggregator::load_initialized(self.aggregator)?;
|
||||
if aggregator.owner != self.aggregator_owner.key.to_bytes() {
|
||||
return Err(Error::OwnerMismatch)?;
|
||||
}
|
||||
aggregator.authorize(self.aggregator_owner)?;
|
||||
|
||||
let oracle = Oracle::load_initialized(self.oracle)?;
|
||||
if oracle.aggregator != self.aggregator.key.to_bytes() {
|
||||
|
@ -142,10 +130,7 @@ impl<'a> SubmitContext<'a> {
|
|||
fn process(&self) -> ProgramResult {
|
||||
let mut aggregator = Aggregator::load_initialized(self.aggregator)?;
|
||||
let mut oracle = Oracle::load_initialized(self.oracle)?;
|
||||
|
||||
if !self.oracle_owner.is_signer {
|
||||
return Err(ProgramError::MissingRequiredSignature);
|
||||
}
|
||||
oracle.authorize(self.oracle_owner)?;
|
||||
|
||||
if oracle.aggregator != self.aggregator.key.to_bytes() {
|
||||
return Err(Error::AggregatorMismatch)?;
|
||||
|
@ -256,15 +241,53 @@ impl<'a> SubmitContext<'a> {
|
|||
}
|
||||
|
||||
// Withdraw token from reward faucet to receiver account, deducting oracle's withdrawable credit.
|
||||
struct WithdrawContext<'a> {
|
||||
token: &'a AccountInfo<'a>,
|
||||
struct WithdrawContext<'a, 'b> {
|
||||
token_program: &'a AccountInfo<'a>,
|
||||
faucet: &'a AccountInfo<'a>,
|
||||
faucet_owner: &'a AccountInfo<'a>, // program signed
|
||||
|
||||
oracle: &'a AccountInfo<'a>,
|
||||
oracle_owner: &'a AccountInfo<'a>, // signed
|
||||
|
||||
receiver: &'a AccountInfo<'a>,
|
||||
|
||||
faucet_owner_seed: &'b [u8],
|
||||
}
|
||||
|
||||
impl<'a, 'b> WithdrawContext<'a, 'b> {
|
||||
fn process(&self) -> ProgramResult {
|
||||
let mut oracle = Oracle::load_initialized(self.oracle)?;
|
||||
oracle.authorize(&self.oracle_owner)?;
|
||||
|
||||
if oracle.withdrawable == 0 {
|
||||
return Err(Error::InsufficientWithdrawable)?;
|
||||
}
|
||||
|
||||
let amount = oracle.withdrawable;
|
||||
|
||||
oracle.withdrawable = 0;
|
||||
oracle.save(self.oracle)?;
|
||||
|
||||
let inx = spl_token::instruction::transfer(
|
||||
self.token_program.key,
|
||||
self.faucet.key,
|
||||
self.receiver.key,
|
||||
self.faucet_owner.key,
|
||||
&[],
|
||||
amount,
|
||||
)?;
|
||||
|
||||
invoke_signed(
|
||||
&inx,
|
||||
&[
|
||||
self.token_program.clone(),
|
||||
self.faucet.clone(),
|
||||
self.faucet_owner.clone(),
|
||||
self.receiver.clone(),
|
||||
],
|
||||
&[&[self.faucet_owner_seed]],
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Program state handler.
|
||||
|
@ -314,11 +337,18 @@ impl Processor {
|
|||
value,
|
||||
}
|
||||
.process(),
|
||||
_ => Err(ProgramError::InvalidInstructionData),
|
||||
// Instruction::Withdraw { amount, seed } => {
|
||||
// msg!("Instruction: Withdraw");
|
||||
// Self::process_withdraw(accounts, amount, seed)
|
||||
// }
|
||||
// _ => Err(ProgramError::InvalidInstructionData),
|
||||
Instruction::Withdraw { faucet_owner_seed } => WithdrawContext {
|
||||
token_program: accounts.get(0)?,
|
||||
faucet: accounts.get(1)?,
|
||||
faucet_owner: accounts.get(2)?,
|
||||
oracle: accounts.get(3)?,
|
||||
oracle_owner: accounts.get(4)?,
|
||||
receiver: accounts.get(5)?,
|
||||
|
||||
faucet_owner_seed: &faucet_owner_seed[..],
|
||||
}
|
||||
.process(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,35 @@
|
|||
//! State transition types
|
||||
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
|
||||
|
||||
use crate::borsh_state::{BorshState, InitBorshState};
|
||||
use crate::instruction::MAX_ORACLES;
|
||||
use crate::{
|
||||
borsh_state::{BorshState, InitBorshState},
|
||||
error::Error,
|
||||
};
|
||||
|
||||
use solana_program::program_pack::IsInitialized;
|
||||
use solana_program::{
|
||||
account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
|
||||
program_pack::IsInitialized,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, BorshSchema, Default, PartialEq)]
|
||||
pub struct Pubkey([u8; 32]);
|
||||
|
||||
pub trait Authority {
|
||||
fn authority(&self) -> Pubkey;
|
||||
|
||||
fn authorize(&self, account: &AccountInfo) -> ProgramResult {
|
||||
if !account.is_signer {
|
||||
return Err(ProgramError::MissingRequiredSignature);
|
||||
}
|
||||
|
||||
if self.authority().0 != account.key.to_bytes() {
|
||||
return Err(Error::OwnerMismatch)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, BorshSchema, Default, PartialEq)]
|
||||
pub struct AggregatorConfig {
|
||||
|
@ -62,12 +87,16 @@ pub struct Aggregator {
|
|||
pub answer: Answer,
|
||||
}
|
||||
|
||||
impl Authority for Aggregator {
|
||||
fn authority(&self) -> Pubkey {
|
||||
Pubkey(self.owner)
|
||||
}
|
||||
}
|
||||
impl IsInitialized for Aggregator {
|
||||
fn is_initialized(&self) -> bool {
|
||||
self.is_initialized
|
||||
}
|
||||
}
|
||||
|
||||
impl BorshState for Aggregator {}
|
||||
impl InitBorshState for Aggregator {}
|
||||
|
||||
|
@ -106,6 +135,11 @@ pub struct Oracle {
|
|||
/// owner
|
||||
pub owner: [u8; 32],
|
||||
}
|
||||
impl Authority for Oracle {
|
||||
fn authority(&self) -> Pubkey {
|
||||
Pubkey(self.owner)
|
||||
}
|
||||
}
|
||||
impl BorshState for Oracle {}
|
||||
impl IsInitialized for Oracle {
|
||||
fn is_initialized(&self) -> bool {
|
||||
|
|
Loading…
Reference in New Issue