diff --git a/src/bank.rs b/src/bank.rs index 02ace88447..cb6ea9e6bb 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -25,7 +25,8 @@ pub const MAX_ENTRY_IDS: usize = 1024 * 4; pub enum BankError { AccountNotFound(PublicKey), InsufficientFunds(PublicKey), - InvalidTransferSignature(Signature), + InvalidTxSignature(Signature), + InvalidTxTokens, } pub type Result = result::Result; @@ -161,6 +162,9 @@ impl Bank { fn apply_debits(&self, tx: &Transaction) -> Result<()> { if let Instruction::NewContract(contract) = &tx.instruction { trace!("Transaction {}", contract.tokens); + if contract.tokens < 0 { + return Err(BankError::InvalidTxTokens); + } } let bals = self.balances .read() @@ -172,7 +176,7 @@ impl Bank { } if !self.reserve_signature_with_last_id(&tx.sig, &tx.last_id) { - return Err(BankError::InvalidTransferSignature(tx.sig)); + return Err(BankError::InvalidTxSignature(tx.sig)); } loop { @@ -403,6 +407,18 @@ mod tests { assert_eq!(bank.transaction_count(), 2); } + #[test] + fn test_invalid_tokens() { + let mint = Mint::new(1); + let pubkey = KeyPair::new().pubkey(); + let bank = Bank::new(&mint); + assert_eq!( + bank.transfer(-1, &mint.keypair(), pubkey, mint.last_id()), + Err(BankError::InvalidTxTokens) + ); + assert_eq!(bank.transaction_count(), 0); + } + #[test] fn test_account_not_found() { let mint = Mint::new(1); diff --git a/src/transaction.rs b/src/transaction.rs index a9683b3114..083e93637b 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -154,7 +154,8 @@ impl Transaction { pub fn verify_plan(&self) -> bool { if let Instruction::NewContract(contract) = &self.instruction { - contract.plan.verify(contract.tokens - self.fee) + self.fee >= 0 && self.fee <= contract.tokens + && contract.plan.verify(contract.tokens - self.fee) } else { true } @@ -208,10 +209,10 @@ mod tests { fn test_transfer_with_fee() { let zero = Hash::default(); let keypair0 = KeyPair::new(); - let keypair1 = KeyPair::new(); - let pubkey1 = keypair1.pubkey(); - let tx0 = Transaction::new_taxed(&keypair0, pubkey1, 42, 1, zero); - assert!(tx0.verify_plan()); + let pubkey1 = KeyPair::new().pubkey(); + assert!(Transaction::new_taxed(&keypair0, pubkey1, 1, 1, zero).verify_plan()); + assert!(!Transaction::new_taxed(&keypair0, pubkey1, 1, 2, zero).verify_plan()); + assert!(!Transaction::new_taxed(&keypair0, pubkey1, 1, -1, zero).verify_plan()); } #[test]