Skip to content

Commit 290a712

Browse files
committed
created challenge struct
0 parents  commit 290a712

File tree

3 files changed

+103
-0
lines changed

3 files changed

+103
-0
lines changed

Diff for: .gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
Cargo.lock

Diff for: Cargo.toml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "sol-ctf-framework"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
poc-framework = { git = "https://github.com/otter-sec/solana-poc-framework" }
10+
tempfile = "*"

Diff for: src/lib.rs

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use std::error::Error;
2+
use std::io::{BufRead, Write};
3+
use std::str::FromStr;
4+
5+
use poc_framework::solana_sdk::instruction::{AccountMeta, Instruction};
6+
use poc_framework::solana_sdk::signature::Keypair;
7+
use poc_framework::{Environment, LocalEnvironment, solana_sdk::pubkey::Pubkey, solana_transaction_status::EncodedConfirmedTransaction};
8+
use tempfile::NamedTempFile;
9+
pub struct Challenge<R: BufRead, W: Write> {
10+
input: R,
11+
output: W,
12+
pub env: LocalEnvironment
13+
}
14+
15+
impl<R: BufRead, W: Write> Challenge<R, W> {
16+
pub fn new(input: R, output: W) -> Challenge<R, W> {
17+
let env = LocalEnvironment::builder().build();
18+
Challenge {
19+
input,
20+
output,
21+
env,
22+
}
23+
}
24+
25+
/// Reads program from input and deploys on environment
26+
pub fn input_program(&mut self) -> Result<Pubkey, Box<dyn Error>> {
27+
let mut line = String::new();
28+
writeln!(self.output, "program len: ")?;
29+
self.input.read_line(&mut line)?;
30+
let len: usize = line.trim().parse()?;
31+
32+
let mut input_so = vec![0; len];
33+
self.input.read_exact(&mut input_so)?;
34+
35+
let mut input_file = NamedTempFile::new()?;
36+
input_file.write_all(&input_so)?;
37+
38+
let program_address = self.env.deploy_program(input_file.path());
39+
Ok(program_address)
40+
}
41+
42+
/// Reads instruction accounts/data from input and sends in transaction to specified program
43+
///
44+
/// # Account Format:
45+
/// `[meta] [pubkey]`
46+
///
47+
/// `[meta]` - contains "s" if account is a signer, "w" if it is writable
48+
/// `[pubkey]` - the address of the account
49+
pub fn input_instruction(&mut self, program_id: Pubkey, signers: &[&Keypair]) -> Result<EncodedConfirmedTransaction, Box<dyn Error>> {
50+
let mut line = String::new();
51+
writeln!(self.output, "num accounts: ")?;
52+
self.input.read_line(&mut line)?;
53+
let num_accounts: usize = line.trim().parse()?;
54+
55+
let mut metas = vec![];
56+
for _ in 0..num_accounts {
57+
line.clear();
58+
self.input.read_line(&mut line)?;
59+
60+
let mut it = line.trim().split(' ');
61+
let meta = it.next().ok_or("bad meta")?;
62+
let pubkey = it.next().ok_or("bad pubkey")?;
63+
let pubkey = Pubkey::from_str(pubkey)?;
64+
65+
let is_signer = meta.contains('s');
66+
let is_writable = meta.contains('w');
67+
68+
if is_writable {
69+
metas.push(AccountMeta::new(pubkey, is_signer));
70+
} else {
71+
metas.push(AccountMeta::new_readonly(pubkey, is_signer));
72+
}
73+
}
74+
75+
line.clear();
76+
writeln!(self.output, "ix len")?;
77+
self.input.read_line(&mut line)?;
78+
let ix_data_len: usize = line.trim().parse()?;
79+
let mut ix_data = vec![0; ix_data_len];
80+
81+
self.input.read_exact(&mut ix_data)?;
82+
83+
let ix = Instruction::new_with_bytes(
84+
program_id,
85+
&ix_data,
86+
metas
87+
);
88+
89+
Ok(self.env.execute_as_transaction(&[ix], signers))
90+
}
91+
}

0 commit comments

Comments
 (0)