cougr_core/accounts/
replay.rs1use soroban_sdk::{Address, Env, Symbol};
2
3use super::error::AccountError;
4
5const ACCOUNT_NONCE_PREFIX: &str = "acct_nonce";
6
7pub struct ReplayProtection;
9
10impl ReplayProtection {
11 pub fn next_account_nonce(env: &Env, account: &Address) -> u64 {
12 let key = Self::storage_key(env, account);
13 env.storage().persistent().get(&key).unwrap_or(0)
14 }
15
16 pub fn verify_and_consume_account_nonce(
17 env: &Env,
18 account: &Address,
19 nonce: u64,
20 ) -> Result<u64, AccountError> {
21 let expected = Self::next_account_nonce(env, account);
22 if nonce != expected {
23 return Err(AccountError::NonceMismatch);
24 }
25 env.storage()
26 .persistent()
27 .set(&Self::storage_key(env, account), &(expected + 1));
28 Ok(expected)
29 }
30
31 fn storage_key(env: &Env, account: &Address) -> (Symbol, Address) {
32 (Symbol::new(env, ACCOUNT_NONCE_PREFIX), account.clone())
33 }
34}