2020-11-26 14:19:50 -08:00
|
|
|
//! Program state processor
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
error::Error,
|
2020-12-07 19:57:03 -08:00
|
|
|
instruction::{Instruction, PAYMENT_AMOUNT},
|
|
|
|
state::{Aggregator, Oracle, Submission},
|
2020-11-26 14:19:50 -08:00
|
|
|
};
|
2020-11-27 22:52:54 -08:00
|
|
|
|
2020-11-26 14:19:50 -08:00
|
|
|
use num_traits::FromPrimitive;
|
|
|
|
use solana_program::{
|
|
|
|
account_info::{next_account_info, AccountInfo},
|
2020-11-27 22:52:54 -08:00
|
|
|
clock::{Clock},
|
2020-11-26 14:19:50 -08:00
|
|
|
decode_error::DecodeError,
|
|
|
|
entrypoint::ProgramResult,
|
2020-11-27 01:38:49 -08:00
|
|
|
info,
|
2020-11-26 14:19:50 -08:00
|
|
|
program_pack::{Pack},
|
2020-12-04 04:11:10 -08:00
|
|
|
program::{invoke_signed},
|
2020-11-27 22:52:54 -08:00
|
|
|
program_error::{PrintProgramError, ProgramError},
|
2020-11-26 14:19:50 -08:00
|
|
|
pubkey::Pubkey,
|
|
|
|
sysvar::{rent::Rent, Sysvar},
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Program state handler.
|
|
|
|
pub struct Processor {}
|
|
|
|
|
|
|
|
impl Processor {
|
|
|
|
/// Processes an [Instruction](enum.Instruction.html).
|
2020-12-01 19:42:09 -08:00
|
|
|
pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult {
|
2020-11-26 14:19:50 -08:00
|
|
|
let instruction = Instruction::unpack(input)?;
|
|
|
|
|
|
|
|
match instruction {
|
|
|
|
Instruction::Initialize {
|
2020-12-07 19:57:03 -08:00
|
|
|
submit_interval,
|
2020-11-26 14:19:50 -08:00
|
|
|
min_submission_value,
|
|
|
|
max_submission_value,
|
2020-12-02 22:45:16 -08:00
|
|
|
description,
|
2020-11-26 14:19:50 -08:00
|
|
|
} => {
|
|
|
|
info!("Instruction: Initialize");
|
|
|
|
Self::process_initialize(
|
2020-12-07 19:57:03 -08:00
|
|
|
program_id, accounts, submit_interval, min_submission_value,
|
2020-12-02 22:45:16 -08:00
|
|
|
max_submission_value, description,
|
2020-11-26 14:19:50 -08:00
|
|
|
)
|
|
|
|
},
|
|
|
|
Instruction::AddOracle {
|
2020-11-30 09:41:09 -08:00
|
|
|
description,
|
2020-11-26 14:19:50 -08:00
|
|
|
} => {
|
|
|
|
info!("Instruction: AddOracle");
|
2020-11-27 01:38:49 -08:00
|
|
|
Self::process_add_oracle(
|
2020-12-01 02:50:31 -08:00
|
|
|
accounts, description,
|
2020-11-27 01:38:49 -08:00
|
|
|
)
|
2020-11-26 14:19:50 -08:00
|
|
|
},
|
|
|
|
Instruction::RemoveOracle {
|
2020-12-01 02:50:31 -08:00
|
|
|
oracle,
|
2020-11-26 14:19:50 -08:00
|
|
|
} => {
|
|
|
|
info!("Instruction: RemoveOracle");
|
2020-11-27 22:52:54 -08:00
|
|
|
Self::process_remove_oracle(
|
2020-12-01 02:50:31 -08:00
|
|
|
accounts, oracle,
|
2020-11-27 22:52:54 -08:00
|
|
|
)
|
2020-11-26 14:19:50 -08:00
|
|
|
},
|
|
|
|
Instruction::Submit {
|
|
|
|
submission,
|
|
|
|
} => {
|
|
|
|
info!("Instruction: Submit");
|
2020-11-27 22:52:54 -08:00
|
|
|
Self::process_submit(
|
|
|
|
accounts, submission,
|
|
|
|
)
|
2020-11-26 14:19:50 -08:00
|
|
|
},
|
2020-11-30 09:41:09 -08:00
|
|
|
Instruction::Withdraw {
|
|
|
|
amount,
|
2020-12-02 22:45:16 -08:00
|
|
|
seed,
|
2020-11-30 09:41:09 -08:00
|
|
|
} => {
|
|
|
|
info!("Instruction: Withdraw");
|
|
|
|
Self::process_withdraw(
|
2020-12-02 22:45:16 -08:00
|
|
|
accounts, amount, seed.as_slice(),
|
2020-11-30 09:41:09 -08:00
|
|
|
)
|
|
|
|
},
|
2020-11-26 14:19:50 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Processes an [Initialize](enum.Instruction.html) instruction.
|
2020-11-30 09:41:09 -08:00
|
|
|
///
|
|
|
|
/// Accounts expected by this instruction:
|
|
|
|
///
|
2020-12-04 04:11:10 -08:00
|
|
|
/// 1. `[]` Sysvar rent
|
|
|
|
/// 2. `[writable, signer]` The aggregator autority
|
2020-11-26 14:19:50 -08:00
|
|
|
pub fn process_initialize(
|
2020-12-07 19:57:03 -08:00
|
|
|
_program_id: &Pubkey,
|
2020-11-26 14:19:50 -08:00
|
|
|
accounts: &[AccountInfo],
|
2020-12-07 19:57:03 -08:00
|
|
|
submit_interval: u32,
|
2020-11-26 14:19:50 -08:00
|
|
|
min_submission_value: u64,
|
|
|
|
max_submission_value: u64,
|
2020-12-02 22:45:16 -08:00
|
|
|
description: [u8; 32],
|
2020-11-26 14:19:50 -08:00
|
|
|
) -> ProgramResult {
|
2020-12-01 19:42:09 -08:00
|
|
|
|
2020-11-26 14:19:50 -08:00
|
|
|
let account_info_iter = &mut accounts.iter();
|
2020-12-01 19:42:09 -08:00
|
|
|
|
2020-11-30 09:41:09 -08:00
|
|
|
let rent_info = next_account_info(account_info_iter)?;
|
2020-12-04 04:11:10 -08:00
|
|
|
let aggregator_info = next_account_info(account_info_iter)?;
|
|
|
|
|
2020-11-30 09:41:09 -08:00
|
|
|
// check signer
|
2020-12-04 04:11:10 -08:00
|
|
|
if !aggregator_info.is_signer {
|
2020-11-30 09:41:09 -08:00
|
|
|
return Err(ProgramError::MissingRequiredSignature);
|
|
|
|
}
|
2020-12-01 19:42:09 -08:00
|
|
|
|
2020-11-30 09:41:09 -08:00
|
|
|
let rent = &Rent::from_account_info(rent_info)?;
|
2020-11-26 14:19:50 -08:00
|
|
|
|
|
|
|
let mut aggregator = Aggregator::unpack_unchecked(&aggregator_info.data.borrow())?;
|
|
|
|
if aggregator.is_initialized {
|
|
|
|
return Err(Error::AlreadyInUse.into());
|
|
|
|
}
|
|
|
|
|
2020-11-30 09:41:09 -08:00
|
|
|
if !rent.is_exempt(aggregator_info.lamports(), aggregator_info.data_len()) {
|
2020-11-26 14:19:50 -08:00
|
|
|
return Err(Error::NotRentExempt.into());
|
|
|
|
}
|
2020-12-01 19:42:09 -08:00
|
|
|
|
2020-12-07 19:57:03 -08:00
|
|
|
aggregator.submit_interval = submit_interval;
|
2020-11-26 14:19:50 -08:00
|
|
|
aggregator.min_submission_value = min_submission_value;
|
|
|
|
aggregator.max_submission_value = max_submission_value;
|
|
|
|
aggregator.description = description;
|
|
|
|
aggregator.is_initialized = true;
|
2020-11-30 09:41:09 -08:00
|
|
|
|
2020-11-26 14:19:50 -08:00
|
|
|
Aggregator::pack(aggregator, &mut aggregator_info.data.borrow_mut())?;
|
2020-12-01 19:42:09 -08:00
|
|
|
|
2020-11-26 14:19:50 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Processes an [AddOracle](enum.Instruction.html) instruction.
|
2020-11-27 22:52:54 -08:00
|
|
|
///
|
2020-12-01 02:50:31 -08:00
|
|
|
/// @description: the oracle name
|
2020-11-27 22:52:54 -08:00
|
|
|
///
|
|
|
|
/// Accounts expected by this instruction:
|
|
|
|
///
|
2020-12-01 19:42:09 -08:00
|
|
|
/// 0. `[writable]` The oracle(key)
|
|
|
|
/// 1. `[]` Clock sysvar
|
|
|
|
/// 2. `[writable, signer]` The aggregator's authority.
|
2020-11-26 14:19:50 -08:00
|
|
|
pub fn process_add_oracle(
|
2020-11-27 01:38:49 -08:00
|
|
|
accounts: &[AccountInfo],
|
2020-11-30 09:41:09 -08:00
|
|
|
description: [u8; 32],
|
2020-11-26 14:19:50 -08:00
|
|
|
) -> ProgramResult {
|
2020-12-01 19:42:09 -08:00
|
|
|
|
2020-11-27 01:38:49 -08:00
|
|
|
let account_info_iter = &mut accounts.iter();
|
2020-12-01 02:50:31 -08:00
|
|
|
let oracle_info = next_account_info(account_info_iter)?;
|
2020-11-27 22:52:54 -08:00
|
|
|
let clock_sysvar_info = next_account_info(account_info_iter)?;
|
2020-12-01 19:42:09 -08:00
|
|
|
let aggregator_info = next_account_info(account_info_iter)?;
|
|
|
|
|
|
|
|
if !aggregator_info.is_signer {
|
|
|
|
return Err(ProgramError::MissingRequiredSignature);
|
|
|
|
}
|
2020-11-27 22:52:54 -08:00
|
|
|
|
2020-12-01 19:42:09 -08:00
|
|
|
let mut aggregator = Aggregator::unpack_unchecked(&aggregator_info.data.borrow())?;
|
2020-11-27 22:52:54 -08:00
|
|
|
|
2020-11-27 01:38:49 -08:00
|
|
|
if !aggregator.is_initialized {
|
|
|
|
return Err(Error::NotFoundAggregator.into());
|
|
|
|
}
|
2020-12-01 19:42:09 -08:00
|
|
|
|
2020-12-04 04:11:10 -08:00
|
|
|
let mut oracle = Oracle::unpack_unchecked(&oracle_info.data.borrow())?;
|
|
|
|
if oracle.is_initialized {
|
|
|
|
return Err(Error::AlreadyInUse.into());
|
|
|
|
}
|
|
|
|
|
2020-12-07 19:57:03 -08:00
|
|
|
// sys clock
|
|
|
|
let clock = &Clock::from_account_info(clock_sysvar_info)?;
|
|
|
|
|
|
|
|
let mut submissions = aggregator.submissions;
|
2020-12-01 19:42:09 -08:00
|
|
|
|
2020-12-07 19:57:03 -08:00
|
|
|
// default submission
|
|
|
|
for s in submissions.iter_mut() {
|
|
|
|
if s.oracle == Pubkey::default() {
|
|
|
|
*s = Submission {
|
|
|
|
time: clock.unix_timestamp,
|
|
|
|
value: 0,
|
|
|
|
oracle: *oracle_info.key,
|
|
|
|
};
|
2020-12-04 04:11:10 -08:00
|
|
|
break;
|
2020-12-01 02:50:31 -08:00
|
|
|
}
|
|
|
|
}
|
2020-11-27 01:38:49 -08:00
|
|
|
|
2020-12-07 19:57:03 -08:00
|
|
|
aggregator.submissions = submissions;
|
2020-11-27 01:38:49 -08:00
|
|
|
Aggregator::pack(aggregator, &mut aggregator_info.data.borrow_mut())?;
|
2020-12-01 19:42:09 -08:00
|
|
|
|
2020-12-01 02:50:31 -08:00
|
|
|
oracle.submission = 0;
|
|
|
|
oracle.next_submit_time = clock.unix_timestamp;
|
|
|
|
oracle.description = description;
|
|
|
|
oracle.is_initialized = true;
|
|
|
|
oracle.withdrawable = 0;
|
2020-12-07 19:57:03 -08:00
|
|
|
oracle.aggregator = *aggregator_info.key;
|
2020-12-01 02:50:31 -08:00
|
|
|
|
|
|
|
Oracle::pack(oracle, &mut oracle_info.data.borrow_mut())?;
|
2020-11-27 01:38:49 -08:00
|
|
|
|
2020-11-26 14:19:50 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Processes an [RemoveOracle](enum.Instruction.html) instruction.
|
2020-11-27 22:52:54 -08:00
|
|
|
///
|
|
|
|
/// @seat: the oracle's index of the aggregator
|
|
|
|
///
|
|
|
|
/// Accounts expected by this instruction:
|
|
|
|
///
|
2020-12-01 19:42:09 -08:00
|
|
|
/// 0. `[writable, signer]` The aggregator's authority.
|
2020-11-26 14:19:50 -08:00
|
|
|
pub fn process_remove_oracle(
|
2020-11-27 22:52:54 -08:00
|
|
|
accounts: &[AccountInfo],
|
2020-12-01 02:50:31 -08:00
|
|
|
oracle: Pubkey,
|
2020-11-26 14:19:50 -08:00
|
|
|
) -> ProgramResult {
|
2020-11-27 22:52:54 -08:00
|
|
|
let account_info_iter = &mut accounts.iter();
|
|
|
|
let aggregator_info = next_account_info(account_info_iter)?;
|
|
|
|
|
2020-12-01 19:42:09 -08:00
|
|
|
if !aggregator_info.is_signer {
|
|
|
|
return Err(ProgramError::MissingRequiredSignature);
|
|
|
|
}
|
|
|
|
|
2020-11-27 22:52:54 -08:00
|
|
|
let mut aggregator = Aggregator::unpack_unchecked(&aggregator_info.data.borrow())?;
|
|
|
|
|
|
|
|
if !aggregator.is_initialized {
|
|
|
|
return Err(Error::NotFoundAggregator.into());
|
|
|
|
}
|
|
|
|
|
2020-12-07 19:57:03 -08:00
|
|
|
// remove submission
|
|
|
|
let mut submissions = aggregator.submissions;
|
2020-11-27 22:52:54 -08:00
|
|
|
|
2020-12-04 04:11:10 -08:00
|
|
|
let mut found = false;
|
2020-12-07 19:57:03 -08:00
|
|
|
for s in submissions.iter_mut() {
|
|
|
|
if s.oracle == oracle {
|
|
|
|
*s = Submission::default();
|
2020-12-04 04:11:10 -08:00
|
|
|
found = true;
|
|
|
|
break;
|
2020-12-01 02:50:31 -08:00
|
|
|
}
|
|
|
|
}
|
2020-11-27 22:52:54 -08:00
|
|
|
|
2020-12-04 04:11:10 -08:00
|
|
|
if !found {
|
|
|
|
return Err(Error::NotFoundOracle.into());
|
|
|
|
}
|
|
|
|
|
2020-12-07 19:57:03 -08:00
|
|
|
aggregator.submissions = submissions;
|
2020-11-27 22:52:54 -08:00
|
|
|
Aggregator::pack(aggregator, &mut aggregator_info.data.borrow_mut())?;
|
|
|
|
|
2020-11-26 14:19:50 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Processes an [Submit](enum.Instruction.html) instruction.
|
2020-11-27 22:52:54 -08:00
|
|
|
/// @submission: the updated data that the oracle is submitting
|
|
|
|
///
|
|
|
|
/// Accounts expected by this instruction:
|
|
|
|
///
|
|
|
|
/// 0. `[writable]` The aggregator(key).
|
|
|
|
/// 1. `[]` Clock sysvar
|
2020-12-01 02:50:31 -08:00
|
|
|
/// 1. `[signer, writable]` The oracle's authority.
|
2020-11-26 14:19:50 -08:00
|
|
|
pub fn process_submit(
|
2020-11-27 22:52:54 -08:00
|
|
|
accounts: &[AccountInfo],
|
|
|
|
submission: u64,
|
|
|
|
) -> ProgramResult {
|
|
|
|
let account_info_iter = &mut accounts.iter();
|
|
|
|
let aggregator_info = next_account_info(account_info_iter)?;
|
|
|
|
let clock_sysvar_info = next_account_info(account_info_iter)?;
|
2020-12-01 02:50:31 -08:00
|
|
|
let oracle_info = next_account_info(account_info_iter)?;
|
2020-11-27 22:52:54 -08:00
|
|
|
|
2020-12-07 19:57:03 -08:00
|
|
|
let mut aggregator = Aggregator::unpack_unchecked(&aggregator_info.data.borrow())?;
|
2020-11-27 22:52:54 -08:00
|
|
|
if !aggregator.is_initialized {
|
|
|
|
return Err(Error::NotFoundAggregator.into());
|
|
|
|
}
|
|
|
|
|
|
|
|
if submission < aggregator.min_submission_value || submission > aggregator.max_submission_value {
|
|
|
|
return Err(Error::SubmissonValueOutOfRange.into());
|
|
|
|
}
|
|
|
|
|
2020-12-01 02:50:31 -08:00
|
|
|
if !oracle_info.is_signer {
|
|
|
|
return Err(ProgramError::MissingRequiredSignature);
|
2020-11-27 22:52:54 -08:00
|
|
|
}
|
|
|
|
|
2020-12-01 02:50:31 -08:00
|
|
|
let mut oracle = Oracle::unpack_unchecked(&oracle_info.data.borrow())?;
|
|
|
|
if !oracle.is_initialized {
|
2020-11-27 22:52:54 -08:00
|
|
|
return Err(Error::NotFoundOracle.into());
|
|
|
|
}
|
|
|
|
|
2020-12-07 19:57:03 -08:00
|
|
|
if &oracle.aggregator != aggregator_info.key {
|
|
|
|
return Err(Error::AggregatorKeyNotMatch.into());
|
|
|
|
}
|
|
|
|
|
2020-12-01 02:50:31 -08:00
|
|
|
let clock = &Clock::from_account_info(clock_sysvar_info)?;
|
2020-12-07 19:57:03 -08:00
|
|
|
|
|
|
|
// check whether the aggregator owned this oracle
|
|
|
|
let mut found = false;
|
|
|
|
let mut submissions = aggregator.submissions;
|
|
|
|
for s in submissions.iter_mut() {
|
|
|
|
if &s.oracle == oracle_info.key {
|
|
|
|
s.value = submission;
|
|
|
|
s.time = clock.unix_timestamp;
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !found {
|
|
|
|
return Err(Error::NotFoundOracle.into());
|
|
|
|
}
|
|
|
|
|
|
|
|
aggregator.submissions = submissions;
|
|
|
|
Aggregator::pack(aggregator, &mut aggregator_info.data.borrow_mut())?;
|
|
|
|
|
2020-12-01 02:50:31 -08:00
|
|
|
if oracle.next_submit_time > clock.unix_timestamp {
|
|
|
|
return Err(Error::SubmissonCooling.into());
|
|
|
|
}
|
|
|
|
|
|
|
|
oracle.submission = submission;
|
|
|
|
oracle.withdrawable += PAYMENT_AMOUNT;
|
2020-12-07 19:57:03 -08:00
|
|
|
oracle.next_submit_time = clock.unix_timestamp + aggregator.submit_interval as i64;
|
2020-12-01 02:50:31 -08:00
|
|
|
|
|
|
|
Oracle::pack(oracle, &mut oracle_info.data.borrow_mut())?;
|
|
|
|
|
2020-11-27 22:52:54 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-11-30 09:41:09 -08:00
|
|
|
/// Processes an [Withdraw](enum.Instruction.html) instruction
|
|
|
|
/// Can only be called by the oracle admin
|
|
|
|
///
|
|
|
|
/// @to: the address to send the token to
|
|
|
|
/// @amount: the amount of token to send
|
|
|
|
///
|
|
|
|
/// Accounts expected by this instruction:
|
|
|
|
///
|
2020-12-02 22:45:16 -08:00
|
|
|
/// 0. `[writable]` The aggregator (key).
|
|
|
|
/// 1. `[writable]` The faucet (which token transfer from)
|
|
|
|
/// 2. `[writable]` The recevier (which token withdraw to)
|
2020-11-30 09:41:09 -08:00
|
|
|
/// 3. `[]` SPL Token program id
|
|
|
|
/// 4. `[]` The faucet owner
|
2020-12-01 02:50:31 -08:00
|
|
|
/// 5. `[signer, writable]` The oracle's authority.
|
2020-11-30 09:41:09 -08:00
|
|
|
pub fn process_withdraw(
|
|
|
|
accounts: &[AccountInfo],
|
|
|
|
amount: u64,
|
2020-12-02 22:45:16 -08:00
|
|
|
seed: &[u8],
|
2020-11-26 14:19:50 -08:00
|
|
|
) -> ProgramResult {
|
2020-11-30 09:41:09 -08:00
|
|
|
let account_info_iter = &mut accounts.iter();
|
|
|
|
let aggregator_info = next_account_info(account_info_iter)?;
|
2020-12-02 22:45:16 -08:00
|
|
|
let faucet_info = next_account_info(account_info_iter)?;
|
2020-11-30 09:41:09 -08:00
|
|
|
let receiver_info = next_account_info(account_info_iter)?;
|
|
|
|
|
|
|
|
let token_program_info = next_account_info(account_info_iter)?;
|
|
|
|
|
|
|
|
let faucet_owner_info = next_account_info(account_info_iter)?;
|
2020-12-01 02:50:31 -08:00
|
|
|
let oracle_info = next_account_info(account_info_iter)?;
|
2020-11-30 09:41:09 -08:00
|
|
|
|
2020-12-01 02:50:31 -08:00
|
|
|
if !oracle_info.is_signer {
|
|
|
|
return Err(ProgramError::MissingRequiredSignature);
|
|
|
|
}
|
|
|
|
|
|
|
|
let aggregator = Aggregator::unpack_unchecked(&aggregator_info.data.borrow())?;
|
2020-11-30 09:41:09 -08:00
|
|
|
if !aggregator.is_initialized {
|
|
|
|
return Err(Error::NotFoundAggregator.into());
|
|
|
|
}
|
|
|
|
|
2020-12-01 02:50:31 -08:00
|
|
|
let mut oracle = Oracle::unpack_unchecked(&oracle_info.data.borrow())?;
|
|
|
|
if !oracle.is_initialized {
|
2020-11-30 09:41:09 -08:00
|
|
|
return Err(Error::NotFoundOracle.into());
|
|
|
|
}
|
|
|
|
|
2020-12-01 02:50:31 -08:00
|
|
|
if oracle.withdrawable < amount {
|
2020-11-30 09:41:09 -08:00
|
|
|
return Err(Error::InsufficientWithdrawable.into());
|
|
|
|
}
|
2020-12-01 02:50:31 -08:00
|
|
|
|
2020-12-02 22:45:16 -08:00
|
|
|
info!("Create transfer instruction...");
|
2020-11-30 09:41:09 -08:00
|
|
|
let instruction = spl_token::instruction::transfer(
|
|
|
|
token_program_info.key,
|
2020-12-02 22:45:16 -08:00
|
|
|
faucet_info.key,
|
2020-11-30 09:41:09 -08:00
|
|
|
receiver_info.key,
|
|
|
|
faucet_owner_info.key,
|
|
|
|
&[],
|
|
|
|
amount,
|
|
|
|
)?;
|
|
|
|
|
|
|
|
info!("Invoke signed...");
|
|
|
|
invoke_signed(
|
|
|
|
&instruction,
|
|
|
|
&[
|
2020-12-02 22:45:16 -08:00
|
|
|
faucet_info.clone(),
|
2020-11-30 09:41:09 -08:00
|
|
|
token_program_info.clone(),
|
|
|
|
receiver_info.clone(),
|
|
|
|
faucet_owner_info.clone(),
|
|
|
|
],
|
2020-12-02 22:45:16 -08:00
|
|
|
&[&[seed]]
|
2020-11-30 09:41:09 -08:00
|
|
|
)?;
|
|
|
|
|
|
|
|
// update oracle
|
2020-12-01 02:50:31 -08:00
|
|
|
oracle.withdrawable -= amount;
|
|
|
|
Oracle::pack(oracle, &mut oracle_info.data.borrow_mut())?;
|
2020-11-30 09:41:09 -08:00
|
|
|
|
2020-11-26 14:19:50 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-11-30 09:41:09 -08:00
|
|
|
}
|
2020-11-26 14:19:50 -08:00
|
|
|
|
|
|
|
impl PrintProgramError for Error {
|
|
|
|
fn print<E>(&self)
|
|
|
|
where
|
|
|
|
E: 'static + std::error::Error + DecodeError<E> + PrintProgramError + FromPrimitive,
|
|
|
|
{
|
|
|
|
match self {
|
|
|
|
Error::InvalidInstruction => info!("Error: Invalid instruction"),
|
|
|
|
Error::AlreadyInUse => info!("Error: Already in use"),
|
|
|
|
Error::NotRentExempt => info!("Error: No rent exempt"),
|
2020-11-27 01:38:49 -08:00
|
|
|
Error::NotFoundAggregator => info!("Error: no found aggregator"),
|
|
|
|
Error::OracleAdded => info!("Error: Oracle added"),
|
2020-11-27 22:52:54 -08:00
|
|
|
Error::OwnerMismatch => info!("Error: Owner mismatch"),
|
|
|
|
Error::NotFoundOracle => info!("Error: Not found oracle"),
|
|
|
|
Error::SubmissonValueOutOfRange => info!("Error: Submisson value out of range"),
|
|
|
|
Error::SubmissonCooling => info!("Submission cooling"),
|
2020-11-30 09:41:09 -08:00
|
|
|
Error::InsufficientWithdrawable => info!("Insufficient withdrawable"),
|
2020-12-07 19:57:03 -08:00
|
|
|
Error::AggregatorKeyNotMatch => info!("Aggregator key not match"),
|
2020-11-26 14:19:50 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|