penumbra_sdk_auction/component/action_handler/dutch/
withdraw.rs1use crate::auction::dutch::ActionDutchAuctionWithdraw;
2use crate::component::AuctionStoreRead;
3use crate::component::DutchAuctionManager;
4use anyhow::{bail, ensure, Context, Result};
5use ark_ff::Zero;
6use async_trait::async_trait;
7use cnidarium::StateWrite;
8use cnidarium_component::ActionHandler;
9use decaf377::Fr;
10
11#[async_trait]
12impl ActionHandler for ActionDutchAuctionWithdraw {
13 type CheckStatelessContext = ();
14 async fn check_stateless(&self, _context: ()) -> Result<()> {
15 ensure!(
16 self.seq >= 1,
17 "the sequence number MUST be greater or equal to 1 (got: {})",
18 self.seq
19 );
20
21 ensure!(
22 self.seq < u64::MAX,
23 "the sequence number maximum is `u64::MAX`"
24 );
25
26 Ok(())
27 }
28
29 async fn check_and_execute<S: StateWrite>(&self, mut state: S) -> Result<()> {
30 let auction_id = self.auction_id;
31
32 let auction_state = state
34 .get_dutch_auction_by_id(auction_id)
35 .await
36 .context("the auction associated with this id is not a dutch auction")?;
37
38 let Some(auction_state) = auction_state else {
39 bail!("no auction found for id {auction_id}")
40 };
41
42 ensure!(
44 self.seq == auction_state.state.sequence.saturating_add(1),
45 "the action sequence number MUST be incremented by one (previous: {}, action: {})",
46 self.seq,
47 auction_state.state.sequence
48 );
49
50 let withdrawn_balance = state.withdraw_auction(auction_state).await?;
53
54 let expected_reserve_commitment = withdrawn_balance.commit(Fr::zero());
56
57 ensure!(
58 self.reserves_commitment == expected_reserve_commitment,
59 "the reported reserve commitment is incorrect"
60 );
61
62 Ok(())
63 }
64}