Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit cd57d1c

Browse files
n00m4daeyakovenko
andauthored
Binary oracle implementation (#1347)
* oracle pair init * update * updates * progress * update * update * progress * builds * update * progress * update * copy pasta * Refactor and add Instruction serializing/deserializing * Add pack/unpack for Pool struct * Implement InitPool instruction * Add unit test and refactor InitPool instruction * Minor changes * Add using deposing token mint decimals in pass and fail mints * Add Deposit instruction processing * Add test for Deposit instruction * Add Withdraw instruction processing * Add test for Withdraw instruction * Add Decide instruction with test * Changes in Withdraw instruciton and add time travel to Decide instruction test * Fix clippy warning * Fix warning with if operator * Fix clippy warnings * Update libs version and minor fixes * Minor changes * Add user_transfer_authority to withdraw instruction and other minor changes * Fix clippy warns * Change return value after serialization * Update tokio and solana-program-test libs version Co-authored-by: Anatoly Yakovenko <[email protected]>
1 parent d0bf715 commit cd57d1c

File tree

12 files changed

+2222
-0
lines changed

12 files changed

+2222
-0
lines changed

Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[workspace]
22
members = [
33
"associated-token-account/program",
4+
"binary-oracle-pair/program",
45
"examples/rust/cross-program-invocation",
56
"examples/rust/custom-heap",
67
"examples/rust/logging",

binary-oracle-pair/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Simple Oracle Pair Token
2+
3+
1. pick a deposit token
4+
2. pick the decider's pubkey
5+
3. pick the mint term end slot
6+
4. pick the decide term end slot, must be after 3
7+
8+
Each deposit token can mint one `Pass` and one `Fail` token up to
9+
the mint term end slot. After the decide term end slot the `Pass`
10+
token converts 1:1 with the deposit token if and only if the decider
11+
had set `pass` before the end of the decide term, otherwise the `Fail`
12+
token converts 1:1 with the deposit token.

binary-oracle-pair/program/Cargo.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[package]
2+
name = "spl-binary-oracle-pair"
3+
version = "0.1.0"
4+
description = "Solana Program Library Binary Oracle Pair"
5+
authors = ["Solana Maintainers <[email protected]>"]
6+
repository = "https://github.com/solana-labs/solana-program-library"
7+
license = "Apache-2.0"
8+
edition = "2018"
9+
10+
[features]
11+
test-bpf = []
12+
13+
[dependencies]
14+
num-derive = "0.3"
15+
num-traits = "0.2"
16+
solana-program = "1.5.14"
17+
spl-token = { version = "3.0", path = "../../token/program", features = [ "no-entrypoint" ] }
18+
thiserror = "1.0"
19+
uint = "0.8"
20+
arbitrary = { version = "0.4", features = ["derive"], optional = true }
21+
borsh = "0.8.2"
22+
23+
[dev-dependencies]
24+
solana-program-test = "1.6.1"
25+
solana-sdk = "1.5.14"
26+
tokio = { version = "1.3.0", features = ["macros"]}
27+
28+
[lib]
29+
crate-type = ["cdylib", "lib"]

binary-oracle-pair/program/Xargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[target.bpfel-unknown-unknown.dependencies.std]
2+
features = []
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//! Program entrypoint definitions
2+
3+
#![cfg(all(target_arch = "bpf", not(feature = "no-entrypoint")))]
4+
5+
use crate::{error::PoolError, processor};
6+
use solana_program::{
7+
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult,
8+
program_error::PrintProgramError, pubkey::Pubkey,
9+
};
10+
11+
entrypoint!(process_instruction);
12+
fn process_instruction(
13+
program_id: &Pubkey,
14+
accounts: &[AccountInfo],
15+
instruction_data: &[u8],
16+
) -> ProgramResult {
17+
if let Err(error) =
18+
processor::Processor::process_instruction(program_id, accounts, instruction_data)
19+
{
20+
// catch the error so we can print it
21+
error.print::<PoolError>();
22+
return Err(error);
23+
}
24+
Ok(())
25+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//! Error types
2+
3+
use num_derive::FromPrimitive;
4+
use num_traits::FromPrimitive;
5+
use solana_program::{
6+
decode_error::DecodeError, msg, program_error::PrintProgramError, program_error::ProgramError,
7+
};
8+
use thiserror::Error;
9+
10+
/// Errors that may be returned by the Binary Oracle Pair program.
11+
#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)]
12+
pub enum PoolError {
13+
/// Pool account already in use
14+
#[error("Pool account already in use")]
15+
AlreadyInUse,
16+
/// Deposit account already in use
17+
#[error("Deposit account already in use")]
18+
DepositAccountInUse,
19+
/// Token mint account already in use
20+
#[error("Token account already in use")]
21+
TokenMintInUse,
22+
/// Invalid seed or bump_seed was provided
23+
#[error("Failed to generate program account because of invalid data")]
24+
InvalidAuthorityData,
25+
/// Invalid authority account provided
26+
#[error("Invalid authority account provided")]
27+
InvalidAuthorityAccount,
28+
/// Lamport balance below rent-exempt threshold.
29+
#[error("Lamport balance below rent-exempt threshold")]
30+
NotRentExempt,
31+
/// Expected an SPL Token mint
32+
#[error("Input token mint account is not valid")]
33+
InvalidTokenMint,
34+
/// Amount should be more than zero
35+
#[error("Amount should be more than zero")]
36+
InvalidAmount,
37+
/// Wrong decider account
38+
#[error("Wrong decider account was sent")]
39+
WrongDeciderAccount,
40+
/// Signature missing in transaction
41+
#[error("Signature missing in transaction")]
42+
SignatureMissing,
43+
/// Decision was already made for this pool
44+
#[error("Decision was already made for this pool")]
45+
DecisionAlreadyMade,
46+
/// Decision can't be made in current slot
47+
#[error("Decision can't be made in current slot")]
48+
InvalidSlotForDecision,
49+
/// Deposit can't be made in current slot
50+
#[error("Deposit can't be made in current slot")]
51+
InvalidSlotForDeposit,
52+
/// No decision has been made yet
53+
#[error("No decision has been made yet")]
54+
NoDecisionMadeYet,
55+
}
56+
57+
impl From<PoolError> for ProgramError {
58+
fn from(e: PoolError) -> Self {
59+
ProgramError::Custom(e as u32)
60+
}
61+
}
62+
63+
impl<T> DecodeError<T> for PoolError {
64+
fn type_of() -> &'static str {
65+
"Binary Oracle Pair Error"
66+
}
67+
}
68+
69+
impl PrintProgramError for PoolError {
70+
fn print<E>(&self)
71+
where
72+
E: 'static + std::error::Error + DecodeError<E> + PrintProgramError + FromPrimitive,
73+
{
74+
match self {
75+
PoolError::AlreadyInUse => msg!("Error: Pool account already in use"),
76+
PoolError::DepositAccountInUse => msg!("Error: Deposit account already in use"),
77+
PoolError::TokenMintInUse => msg!("Error: Token account already in use"),
78+
PoolError::InvalidAuthorityData => {
79+
msg!("Error: Failed to generate program account because of invalid data")
80+
}
81+
PoolError::InvalidAuthorityAccount => msg!("Error: Invalid authority account provided"),
82+
PoolError::NotRentExempt => msg!("Error: Lamport balance below rent-exempt threshold"),
83+
PoolError::InvalidTokenMint => msg!("Error: Input token mint account is not valid"),
84+
PoolError::InvalidAmount => msg!("Error: Amount should be more than zero"),
85+
PoolError::WrongDeciderAccount => msg!("Error: Wrong decider account was sent"),
86+
PoolError::SignatureMissing => msg!("Error: Signature missing in transaction"),
87+
PoolError::DecisionAlreadyMade => {
88+
msg!("Error: Decision was already made for this pool")
89+
}
90+
PoolError::InvalidSlotForDecision => {
91+
msg!("Error: Decision can't be made in current slot")
92+
}
93+
PoolError::InvalidSlotForDeposit => msg!("Deposit can't be made in current slot"),
94+
PoolError::NoDecisionMadeYet => msg!("Error: No decision has been made yet"),
95+
}
96+
}
97+
}

0 commit comments

Comments
 (0)