diff --git a/contracts/token-vault/src/errors.rs b/contracts/token-vault/src/errors.rs index 4f8011c6..706acb6c 100644 --- a/contracts/token-vault/src/errors.rs +++ b/contracts/token-vault/src/errors.rs @@ -1,7 +1,7 @@ use soroban_sdk::contracterror; -#[contracterror] -#[derive(Copy, Clone, Eq, PartialEq, Debug)] +#contracterror +#derive(Copy, Clone, Eq, Partial, Debug) pub enum Error { InvalidAmount = 1, ArithmeticOverflow = 2, @@ -24,4 +24,8 @@ pub enum Error { NoPendingOwner = 11, /// `accept_owner` was called by an address that is not the pending owner. NotPendingOwner = 12, + /// The token transfer did not move exactly the expected amount for `deposit`. + DepositTransferFailed = 13, + /// The token transfer did not move exactly the expected amount for `withdraw`. + WithdrawTransferFailed = 14, } diff --git a/contracts/token-vault/src/lib.rs b/contracts/token-vault/src/lib.rs index 328245f8..a3ef4805 100644 --- a/contracts/token-vault/src/lib.rs +++ b/contracts/token-vault/src/lib.rs @@ -129,6 +129,9 @@ impl TokenVault { if new_balance > max { return Err(Error::LimitExceeded); } + if new_balance != expected_balance { + return Err(Error::DepositTransferFailed); + } bump_instance(&env); events::deposited(&env, &from, amount, new_balance); @@ -145,12 +148,16 @@ impl TokenVault { } let balance = vault_balance(&env)?; - let new_balance = balance + let expected_balance = balance .checked_sub(amount) .ok_or(Error::ArithmeticOverflow)?; let tk = token_client(&env)?; tk.transfer(&env.current_contract_address(), &to, &amount); + let new_balance = vault_balance(&env)?; + if new_balance != expected_balance { + return Err(Error::DepositTransferFailed); + } bump_instance(&env); events::withdrawn(&env, &caller, &to, amount, new_balance); diff --git a/contracts/token-vault/src/storage.rs b/contracts/token-vault/src/storage.rs index 3e4def6f..3b2007d2 100644 --- a/contracts/token-vault/src/storage.rs +++ b/contracts/token-vault/src/storage.rs @@ -1,7 +1,7 @@ -use soroban_sdk::{contracttype, Address, Env}; +use soroban_sdk:{contracttype, Address, Env}; #[contracttype] -#[derive(Clone)] +#derive(Clone) pub enum DataKey { Owner, Token, @@ -15,7 +15,7 @@ pub enum DataKey { /// Absent key means no operator has been delegated. Operator, /// Emergency-pause flag. When `true`, all state-mutating entry points - /// (`deposit`, `withdraw`, `set_limit`) revert before touching state. + /// (deposit, withdraw, set_limit) revert before touching state. Paused, /// Pending owner address for the 2-step owner transfer. /// Set by `propose_owner`, consumed by `accept_owner`. @@ -45,16 +45,14 @@ pub fn set_max_limit(env: &Env, v: &i128) { env.storage().instance().set(&DataKey::MaxLimit, v); } -pub fn get_max_limit(env: &Env) -> Option { +pub fn get_max_limit(env: &Env) -> Option>i128> { env.storage().instance().get(&DataKey::MaxLimit) } -#[cfg(test)] pub fn set_balance(env: &Env, v: &i128) { env.storage().instance().set(&DataKey::Balance, v); } -#[cfg(test)] pub fn get_balance(env: &Env) -> Option { env.storage().instance().get(&DataKey::Balance) }