Rename BudgetState to BudgetProgram
This commit is contained in:
parent
d5adec20a3
commit
b3d2c900cd
19
src/bank.rs
19
src/bank.rs
|
@ -6,7 +6,7 @@
|
|||
use bincode::deserialize;
|
||||
use bincode::serialize;
|
||||
use bpf_loader;
|
||||
use budget_program::BudgetState;
|
||||
use budget_program::BudgetProgram;
|
||||
use counter::Counter;
|
||||
use entry::Entry;
|
||||
use itertools::Itertools;
|
||||
|
@ -827,8 +827,9 @@ impl Bank {
|
|||
};
|
||||
return Err(err);
|
||||
}
|
||||
} else if BudgetState::check_id(&program_id) {
|
||||
if BudgetState::process_transaction(&tx, instruction_index, program_accounts).is_err() {
|
||||
} else if BudgetProgram::check_id(&program_id) {
|
||||
if BudgetProgram::process_transaction(&tx, instruction_index, program_accounts).is_err()
|
||||
{
|
||||
return Err(BankError::ProgramRuntimeError(instruction_index as u8));
|
||||
}
|
||||
} else if StorageProgram::check_id(&program_id) {
|
||||
|
@ -1310,8 +1311,8 @@ impl Bank {
|
|||
pub fn read_balance(account: &Account) -> u64 {
|
||||
if SystemProgram::check_id(&account.owner) {
|
||||
SystemProgram::get_balance(account)
|
||||
} else if BudgetState::check_id(&account.owner) {
|
||||
BudgetState::get_balance(account)
|
||||
} else if BudgetProgram::check_id(&account.owner) {
|
||||
BudgetProgram::get_balance(account)
|
||||
} else {
|
||||
account.tokens
|
||||
}
|
||||
|
@ -1497,7 +1498,7 @@ impl Bank {
|
|||
mod tests {
|
||||
use super::*;
|
||||
use bincode::serialize;
|
||||
use budget_program::BudgetState;
|
||||
use budget_program::BudgetProgram;
|
||||
use entry::next_entry;
|
||||
use entry::Entry;
|
||||
use jsonrpc_macros::pubsub::{Subscriber, SubscriptionId};
|
||||
|
@ -2020,7 +2021,7 @@ mod tests {
|
|||
last_id,
|
||||
1,
|
||||
16,
|
||||
BudgetState::id(),
|
||||
BudgetProgram::id(),
|
||||
0,
|
||||
);
|
||||
bank.process_transaction(&tx).unwrap();
|
||||
|
@ -2255,7 +2256,7 @@ mod tests {
|
|||
assert_eq!(SystemProgram::id(), system);
|
||||
assert_eq!(native_loader::id(), native);
|
||||
assert_eq!(bpf_loader::id(), bpf);
|
||||
assert_eq!(BudgetState::id(), budget);
|
||||
assert_eq!(BudgetProgram::id(), budget);
|
||||
assert_eq!(StorageProgram::id(), storage);
|
||||
assert_eq!(token_program::id(), token);
|
||||
assert_eq!(VoteProgram::id(), vote);
|
||||
|
@ -2268,7 +2269,7 @@ mod tests {
|
|||
SystemProgram::id(),
|
||||
native_loader::id(),
|
||||
bpf_loader::id(),
|
||||
BudgetState::id(),
|
||||
BudgetProgram::id(),
|
||||
StorageProgram::id(),
|
||||
token_program::id(),
|
||||
VoteProgram::id(),
|
||||
|
|
|
@ -25,7 +25,7 @@ pub enum BudgetError {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
|
||||
pub struct BudgetState {
|
||||
pub struct BudgetProgram {
|
||||
pub initialized: bool,
|
||||
pub pending_budget: Option<BudgetExpr>,
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ const BUDGET_PROGRAM_ID: [u8; 32] = [
|
|||
0,
|
||||
];
|
||||
|
||||
impl BudgetState {
|
||||
impl BudgetProgram {
|
||||
fn is_pending(&self) -> bool {
|
||||
self.pending_budget != None
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ impl BudgetState {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn apply_debits_to_budget_state(
|
||||
fn apply_debits(
|
||||
tx: &Transaction,
|
||||
instruction_index: usize,
|
||||
accounts: &mut [&mut Account],
|
||||
|
@ -131,44 +131,44 @@ impl BudgetState {
|
|||
trace!("contract already exists");
|
||||
Err(BudgetError::ContractAlreadyExists)
|
||||
} else {
|
||||
let mut state = BudgetState::default();
|
||||
state.pending_budget = Some(expr);
|
||||
let mut program = BudgetProgram::default();
|
||||
program.pending_budget = Some(expr);
|
||||
accounts[1].tokens += accounts[0].tokens;
|
||||
accounts[0].tokens = 0;
|
||||
state.initialized = true;
|
||||
state.serialize(&mut accounts[1].userdata)
|
||||
program.initialized = true;
|
||||
program.serialize(&mut accounts[1].userdata)
|
||||
}
|
||||
}
|
||||
}
|
||||
Instruction::ApplyTimestamp(dt) => {
|
||||
if let Ok(mut state) = Self::deserialize(&accounts[1].userdata) {
|
||||
if !state.is_pending() {
|
||||
if let Ok(mut program) = Self::deserialize(&accounts[1].userdata) {
|
||||
if !program.is_pending() {
|
||||
Err(BudgetError::ContractNotPending)
|
||||
} else if !state.initialized {
|
||||
} else if !program.initialized {
|
||||
trace!("contract is uninitialized");
|
||||
Err(BudgetError::UninitializedContract)
|
||||
} else {
|
||||
trace!("apply timestamp");
|
||||
state.apply_timestamp(tx, instruction_index, accounts, *dt)?;
|
||||
program.apply_timestamp(tx, instruction_index, accounts, *dt)?;
|
||||
trace!("apply timestamp committed");
|
||||
state.serialize(&mut accounts[1].userdata)
|
||||
program.serialize(&mut accounts[1].userdata)
|
||||
}
|
||||
} else {
|
||||
Err(BudgetError::UninitializedContract)
|
||||
}
|
||||
}
|
||||
Instruction::ApplySignature => {
|
||||
if let Ok(mut state) = Self::deserialize(&accounts[1].userdata) {
|
||||
if !state.is_pending() {
|
||||
if let Ok(mut program) = Self::deserialize(&accounts[1].userdata) {
|
||||
if !program.is_pending() {
|
||||
Err(BudgetError::ContractNotPending)
|
||||
} else if !state.initialized {
|
||||
} else if !program.initialized {
|
||||
trace!("contract is uninitialized");
|
||||
Err(BudgetError::UninitializedContract)
|
||||
} else {
|
||||
trace!("apply signature");
|
||||
state.apply_signature(tx, instruction_index, accounts)?;
|
||||
program.apply_signature(tx, instruction_index, accounts)?;
|
||||
trace!("apply signature committed");
|
||||
state.serialize(&mut accounts[1].userdata)
|
||||
program.serialize(&mut accounts[1].userdata)
|
||||
}
|
||||
} else {
|
||||
Err(BudgetError::UninitializedContract)
|
||||
|
@ -224,7 +224,7 @@ impl BudgetState {
|
|||
) -> Result<(), BudgetError> {
|
||||
if let Ok(instruction) = deserialize(tx.userdata(instruction_index)) {
|
||||
trace!("process_transaction: {:?}", instruction);
|
||||
Self::apply_debits_to_budget_state(tx, instruction_index, accounts, &instruction)
|
||||
Self::apply_debits(tx, instruction_index, accounts, &instruction)
|
||||
} else {
|
||||
info!(
|
||||
"Invalid transaction userdata: {:?}",
|
||||
|
@ -236,9 +236,9 @@ impl BudgetState {
|
|||
|
||||
//TODO the contract needs to provide a "get_balance" introspection call of the userdata
|
||||
pub fn get_balance(account: &Account) -> u64 {
|
||||
if let Ok(state) = deserialize(&account.userdata) {
|
||||
let state: BudgetState = state;
|
||||
if state.is_pending() {
|
||||
if let Ok(program) = deserialize(&account.userdata) {
|
||||
let program: BudgetProgram = program;
|
||||
if program.is_pending() {
|
||||
0
|
||||
} else {
|
||||
account.tokens
|
||||
|
@ -251,7 +251,7 @@ impl BudgetState {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use bincode::serialize;
|
||||
use budget_program::{BudgetError, BudgetState};
|
||||
use budget_program::{BudgetError, BudgetProgram};
|
||||
use budget_transaction::BudgetTransaction;
|
||||
use chrono::prelude::{DateTime, NaiveDate, Utc};
|
||||
use signature::{GenKeys, Keypair, KeypairUtil};
|
||||
|
@ -262,23 +262,23 @@ mod test {
|
|||
|
||||
fn process_transaction(tx: &Transaction, accounts: &mut [Account]) -> Result<(), BudgetError> {
|
||||
let mut refs: Vec<&mut Account> = accounts.iter_mut().collect();
|
||||
BudgetState::process_transaction(&tx, 0, &mut refs[..])
|
||||
BudgetProgram::process_transaction(&tx, 0, &mut refs[..])
|
||||
}
|
||||
#[test]
|
||||
fn test_serializer() {
|
||||
let mut a = Account::new(0, 512, BudgetState::id());
|
||||
let b = BudgetState::default();
|
||||
let mut a = Account::new(0, 512, BudgetProgram::id());
|
||||
let b = BudgetProgram::default();
|
||||
b.serialize(&mut a.userdata).unwrap();
|
||||
let buf = serialize(&b).unwrap();
|
||||
assert_eq!(a.userdata[8..8 + buf.len()], buf[0..]);
|
||||
let c = BudgetState::deserialize(&a.userdata).unwrap();
|
||||
let c = BudgetProgram::deserialize(&a.userdata).unwrap();
|
||||
assert_eq!(b, c);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serializer_userdata_too_small() {
|
||||
let mut a = Account::new(0, 1, BudgetState::id());
|
||||
let b = BudgetState::default();
|
||||
let mut a = Account::new(0, 1, BudgetProgram::id());
|
||||
let b = BudgetProgram::default();
|
||||
assert_eq!(
|
||||
b.serialize(&mut a.userdata),
|
||||
Err(BudgetError::UserdataTooSmall)
|
||||
|
@ -287,8 +287,8 @@ mod test {
|
|||
#[test]
|
||||
fn test_invalid_instruction() {
|
||||
let mut accounts = vec![
|
||||
Account::new(1, 0, BudgetState::id()),
|
||||
Account::new(0, 512, BudgetState::id()),
|
||||
Account::new(1, 0, BudgetProgram::id()),
|
||||
Account::new(0, 512, BudgetProgram::id()),
|
||||
];
|
||||
let from = Keypair::new();
|
||||
let contract = Keypair::new();
|
||||
|
@ -296,7 +296,7 @@ mod test {
|
|||
let tx = Transaction::new(
|
||||
&from,
|
||||
&[contract.pubkey()],
|
||||
BudgetState::id(),
|
||||
BudgetProgram::id(),
|
||||
&userdata,
|
||||
Hash::default(),
|
||||
0,
|
||||
|
@ -307,12 +307,12 @@ mod test {
|
|||
#[test]
|
||||
fn test_unsigned_witness_key() {
|
||||
let mut accounts = vec![
|
||||
Account::new(1, 0, BudgetState::id()),
|
||||
Account::new(0, 512, BudgetState::id()),
|
||||
Account::new(0, 0, BudgetState::id()),
|
||||
Account::new(1, 0, BudgetProgram::id()),
|
||||
Account::new(0, 512, BudgetProgram::id()),
|
||||
Account::new(0, 0, BudgetProgram::id()),
|
||||
];
|
||||
|
||||
// Initialize BudgetState
|
||||
// Initialize BudgetProgram
|
||||
let from = Keypair::new();
|
||||
let contract = Keypair::new().pubkey();
|
||||
let to = Keypair::new().pubkey();
|
||||
|
@ -346,12 +346,12 @@ mod test {
|
|||
#[test]
|
||||
fn test_unsigned_timestamp() {
|
||||
let mut accounts = vec![
|
||||
Account::new(1, 0, BudgetState::id()),
|
||||
Account::new(0, 512, BudgetState::id()),
|
||||
Account::new(0, 0, BudgetState::id()),
|
||||
Account::new(1, 0, BudgetProgram::id()),
|
||||
Account::new(0, 512, BudgetProgram::id()),
|
||||
Account::new(0, 0, BudgetProgram::id()),
|
||||
];
|
||||
|
||||
// Initialize BudgetState
|
||||
// Initialize BudgetProgram
|
||||
let from = Keypair::new();
|
||||
let contract = Keypair::new().pubkey();
|
||||
let to = Keypair::new().pubkey();
|
||||
|
@ -386,9 +386,9 @@ mod test {
|
|||
#[test]
|
||||
fn test_transfer_on_date() {
|
||||
let mut accounts = vec![
|
||||
Account::new(1, 0, BudgetState::id()),
|
||||
Account::new(0, 512, BudgetState::id()),
|
||||
Account::new(0, 0, BudgetState::id()),
|
||||
Account::new(1, 0, BudgetProgram::id()),
|
||||
Account::new(0, 512, BudgetProgram::id()),
|
||||
Account::new(0, 0, BudgetProgram::id()),
|
||||
];
|
||||
let from_account = 0;
|
||||
let contract_account = 1;
|
||||
|
@ -411,8 +411,8 @@ mod test {
|
|||
process_transaction(&tx, &mut accounts).unwrap();
|
||||
assert_eq!(accounts[from_account].tokens, 0);
|
||||
assert_eq!(accounts[contract_account].tokens, 1);
|
||||
let state = BudgetState::deserialize(&accounts[contract_account].userdata).unwrap();
|
||||
assert!(state.is_pending());
|
||||
let program = BudgetProgram::deserialize(&accounts[contract_account].userdata).unwrap();
|
||||
assert!(program.is_pending());
|
||||
|
||||
// Attack! Try to payout to a rando key
|
||||
let tx = Transaction::budget_new_timestamp(
|
||||
|
@ -430,8 +430,8 @@ mod test {
|
|||
assert_eq!(accounts[contract_account].tokens, 1);
|
||||
assert_eq!(accounts[to_account].tokens, 0);
|
||||
|
||||
let state = BudgetState::deserialize(&accounts[contract_account].userdata).unwrap();
|
||||
assert!(state.is_pending());
|
||||
let program = BudgetProgram::deserialize(&accounts[contract_account].userdata).unwrap();
|
||||
assert!(program.is_pending());
|
||||
|
||||
// Now, acknowledge the time in the condition occurred and
|
||||
// that pubkey's funds are now available.
|
||||
|
@ -447,8 +447,8 @@ mod test {
|
|||
assert_eq!(accounts[contract_account].tokens, 0);
|
||||
assert_eq!(accounts[to_account].tokens, 1);
|
||||
|
||||
let state = BudgetState::deserialize(&accounts[contract_account].userdata).unwrap();
|
||||
assert!(!state.is_pending());
|
||||
let program = BudgetProgram::deserialize(&accounts[contract_account].userdata).unwrap();
|
||||
assert!(!program.is_pending());
|
||||
|
||||
// try to replay the timestamp contract
|
||||
assert_eq!(
|
||||
|
@ -462,9 +462,9 @@ mod test {
|
|||
#[test]
|
||||
fn test_cancel_transfer() {
|
||||
let mut accounts = vec![
|
||||
Account::new(1, 0, BudgetState::id()),
|
||||
Account::new(0, 512, BudgetState::id()),
|
||||
Account::new(0, 0, BudgetState::id()),
|
||||
Account::new(1, 0, BudgetProgram::id()),
|
||||
Account::new(0, 512, BudgetProgram::id()),
|
||||
Account::new(0, 0, BudgetProgram::id()),
|
||||
];
|
||||
let from_account = 0;
|
||||
let contract_account = 1;
|
||||
|
@ -486,8 +486,8 @@ mod test {
|
|||
process_transaction(&tx, &mut accounts).unwrap();
|
||||
assert_eq!(accounts[from_account].tokens, 0);
|
||||
assert_eq!(accounts[contract_account].tokens, 1);
|
||||
let state = BudgetState::deserialize(&accounts[contract_account].userdata).unwrap();
|
||||
assert!(state.is_pending());
|
||||
let program = BudgetProgram::deserialize(&accounts[contract_account].userdata).unwrap();
|
||||
assert!(program.is_pending());
|
||||
|
||||
// Attack! try to put the tokens into the wrong account with cancel
|
||||
let tx =
|
||||
|
@ -532,9 +532,9 @@ mod test {
|
|||
#[test]
|
||||
fn test_userdata_too_small() {
|
||||
let mut accounts = vec![
|
||||
Account::new(1, 0, BudgetState::id()),
|
||||
Account::new(1, 0, BudgetState::id()), // <== userdata is 0, which is not enough
|
||||
Account::new(1, 0, BudgetState::id()),
|
||||
Account::new(1, 0, BudgetProgram::id()),
|
||||
Account::new(1, 0, BudgetProgram::id()), // <== userdata is 0, which is not enough
|
||||
Account::new(1, 0, BudgetProgram::id()),
|
||||
];
|
||||
let from = Keypair::new();
|
||||
let contract = Keypair::new();
|
||||
|
@ -551,7 +551,7 @@ mod test {
|
|||
);
|
||||
|
||||
assert!(process_transaction(&tx, &mut accounts).is_err());
|
||||
assert!(BudgetState::deserialize(&accounts[1].userdata).is_err());
|
||||
assert!(BudgetProgram::deserialize(&accounts[1].userdata).is_err());
|
||||
|
||||
let tx = Transaction::budget_new_timestamp(
|
||||
&from,
|
||||
|
@ -561,7 +561,7 @@ mod test {
|
|||
Hash::default(),
|
||||
);
|
||||
assert!(process_transaction(&tx, &mut accounts).is_err());
|
||||
assert!(BudgetState::deserialize(&accounts[1].userdata).is_err());
|
||||
assert!(BudgetProgram::deserialize(&accounts[1].userdata).is_err());
|
||||
|
||||
// Success if there was no panic...
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use bincode::deserialize;
|
||||
use budget_expr::{BudgetExpr, Condition};
|
||||
use budget_instruction::Instruction;
|
||||
use budget_program::BudgetState;
|
||||
use budget_program::BudgetProgram;
|
||||
use chrono::prelude::*;
|
||||
use payment_plan::Payment;
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
|
@ -85,7 +85,7 @@ impl BudgetTransaction for Transaction {
|
|||
};
|
||||
let budget_instruction = Instruction::NewBudget(BudgetExpr::Pay(payment));
|
||||
|
||||
let program_ids = vec![Pubkey::new(&SYSTEM_PROGRAM_ID), BudgetState::id()];
|
||||
let program_ids = vec![Pubkey::new(&SYSTEM_PROGRAM_ID), BudgetProgram::id()];
|
||||
|
||||
let instructions = vec![
|
||||
transaction::Instruction::new(0, &system_instruction, vec![0, 1]),
|
||||
|
@ -119,7 +119,7 @@ impl BudgetTransaction for Transaction {
|
|||
Self::new(
|
||||
from_keypair,
|
||||
&[contract, to],
|
||||
BudgetState::id(),
|
||||
BudgetProgram::id(),
|
||||
&instruction,
|
||||
last_id,
|
||||
0,
|
||||
|
@ -137,7 +137,7 @@ impl BudgetTransaction for Transaction {
|
|||
Self::new(
|
||||
from_keypair,
|
||||
&[contract, to],
|
||||
BudgetState::id(),
|
||||
BudgetProgram::id(),
|
||||
&instruction,
|
||||
last_id,
|
||||
0,
|
||||
|
@ -167,7 +167,7 @@ impl BudgetTransaction for Transaction {
|
|||
Self::new(
|
||||
from_keypair,
|
||||
&[contract],
|
||||
BudgetState::id(),
|
||||
BudgetProgram::id(),
|
||||
&instruction,
|
||||
last_id,
|
||||
0,
|
||||
|
@ -195,7 +195,7 @@ impl BudgetTransaction for Transaction {
|
|||
Self::new(
|
||||
from_keypair,
|
||||
&[contract],
|
||||
BudgetState::id(),
|
||||
BudgetProgram::id(),
|
||||
&instruction,
|
||||
last_id,
|
||||
0,
|
||||
|
|
|
@ -246,7 +246,7 @@ impl RpcSolPubSub for RpcSolPubSubImpl {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use budget_program::BudgetState;
|
||||
use budget_program::BudgetProgram;
|
||||
use budget_transaction::BudgetTransaction;
|
||||
use jsonrpc_core::futures::sync::mpsc;
|
||||
use mint::Mint;
|
||||
|
@ -400,7 +400,7 @@ mod tests {
|
|||
let witness = Keypair::new();
|
||||
let contract_funds = Keypair::new();
|
||||
let contract_state = Keypair::new();
|
||||
let budget_program_id = BudgetState::id();
|
||||
let budget_program_id = BudgetProgram::id();
|
||||
let loader = Pubkey::default(); // TODO
|
||||
let executable = false; // TODO
|
||||
let bank = Bank::new(&alice);
|
||||
|
|
|
@ -323,7 +323,7 @@ pub fn make_packet_from_transaction(tx: Transaction) -> Packet {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use bincode::serialize;
|
||||
use budget_program::BudgetState;
|
||||
use budget_program::BudgetProgram;
|
||||
use packet::{Packet, SharedPackets};
|
||||
use signature::{Keypair, KeypairUtil};
|
||||
use sigverify;
|
||||
|
@ -429,7 +429,7 @@ mod tests {
|
|||
|
||||
let system_instruction = SystemInstruction::Move { tokens };
|
||||
|
||||
let program_ids = vec![SystemProgram::id(), BudgetState::id()];
|
||||
let program_ids = vec![SystemProgram::id(), BudgetProgram::id()];
|
||||
|
||||
let instructions = vec![transaction::Instruction::new(
|
||||
0,
|
||||
|
|
|
@ -246,7 +246,7 @@ mod test {
|
|||
#[test]
|
||||
fn test_sdk_serialize() {
|
||||
let keypair = Keypair::new();
|
||||
use budget_program::BudgetState;
|
||||
use budget_program::BudgetProgram;
|
||||
|
||||
// CreateAccount
|
||||
let tx = Transaction::system_create(
|
||||
|
@ -255,7 +255,7 @@ mod test {
|
|||
Hash::default(),
|
||||
111,
|
||||
222,
|
||||
BudgetState::id(),
|
||||
BudgetProgram::id(),
|
||||
0,
|
||||
);
|
||||
|
||||
|
@ -287,7 +287,7 @@ mod test {
|
|||
);
|
||||
|
||||
// Assign
|
||||
let tx = Transaction::system_assign(&keypair, Hash::default(), BudgetState::id(), 0);
|
||||
let tx = Transaction::system_assign(&keypair, Hash::default(), BudgetProgram::id(), 0);
|
||||
assert_eq!(
|
||||
tx.userdata(0).to_vec(),
|
||||
vec![
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use bincode::serialize;
|
||||
use bpf_loader;
|
||||
use bs58;
|
||||
use budget_program::BudgetState;
|
||||
use budget_program::BudgetProgram;
|
||||
use budget_transaction::BudgetTransaction;
|
||||
use chrono::prelude::*;
|
||||
use clap::ArgMatches;
|
||||
|
@ -497,7 +497,7 @@ pub fn process_command(config: &WalletConfig) -> Result<String, Box<error::Error
|
|||
|
||||
let contract_funds = Keypair::new();
|
||||
let contract_state = Keypair::new();
|
||||
let budget_program_id = BudgetState::id();
|
||||
let budget_program_id = BudgetProgram::id();
|
||||
|
||||
// Create account for contract funds
|
||||
let tx = Transaction::system_create(
|
||||
|
@ -553,7 +553,7 @@ pub fn process_command(config: &WalletConfig) -> Result<String, Box<error::Error
|
|||
|
||||
let contract_funds = Keypair::new();
|
||||
let contract_state = Keypair::new();
|
||||
let budget_program_id = BudgetState::id();
|
||||
let budget_program_id = BudgetProgram::id();
|
||||
|
||||
// Create account for contract funds
|
||||
let tx = Transaction::system_create(
|
||||
|
|
Loading…
Reference in New Issue