smart_wallet/
validators.rs

1//! Account validators.
2
3use crate::*;
4
5impl<'info> Validate<'info> for CreateSmartWallet<'info> {
6    fn validate(&self) -> Result<()> {
7        Ok(())
8    }
9}
10
11impl<'info> Validate<'info> for Auth<'info> {
12    fn validate(&self) -> Result<()> {
13        invariant!(
14            self.smart_wallet.to_account_info().is_signer,
15            "smart_wallet.is_signer"
16        );
17        Ok(())
18    }
19}
20
21impl<'info> Validate<'info> for CreateTransaction<'info> {
22    fn validate(&self) -> Result<()> {
23        // owner_index check happens later
24        Ok(())
25    }
26}
27
28impl<'info> Validate<'info> for ExecuteTransaction<'info> {
29    fn validate(&self) -> Result<()> {
30        assert_keys_eq!(
31            self.smart_wallet,
32            self.transaction.smart_wallet,
33            "smart_wallet"
34        );
35        invariant!(
36            self.smart_wallet.owner_set_seqno == self.transaction.owner_set_seqno,
37            OwnerSetChanged
38        );
39
40        // Has this been executed already?
41        invariant!(self.transaction.executed_at == -1, AlreadyExecuted);
42
43        let eta = self.transaction.eta;
44        let clock = Clock::get()?;
45        let current_ts = clock.unix_timestamp;
46        msg!("current_ts: {}; eta: {}", current_ts, eta);
47        // Has transaction surpassed timelock?
48        invariant!(current_ts >= eta, TransactionNotReady);
49        if eta != NO_ETA {
50            // Has grace period passed?
51            invariant!(
52                current_ts <= unwrap_int!(eta.checked_add(self.smart_wallet.grace_period)),
53                TransactionIsStale
54            );
55        }
56
57        // Do we have enough signers to execute the TX?
58        let sig_count = self.transaction.num_signers();
59        invariant!(
60            (sig_count as u64) >= self.smart_wallet.threshold,
61            NotEnoughSigners
62        );
63
64        // ensure that the owner is a signer
65        // this prevents common frontrunning/flash loan attacks
66        self.smart_wallet.try_owner_index(self.owner.key())?;
67
68        Ok(())
69    }
70}
71
72impl<'info> Validate<'info> for OwnerInvokeInstruction<'info> {
73    fn validate(&self) -> Result<()> {
74        self.smart_wallet.try_owner_index(self.owner.key())?;
75        Ok(())
76    }
77}
78
79impl<'info> Validate<'info> for CreateSubaccountInfo<'info> {
80    fn validate(&self) -> Result<()> {
81        // no validation necessary
82        Ok(())
83    }
84}