penumbra_sdk_governance/action_handler/
deposit_claim.rs1use anyhow::Result;
2use async_trait::async_trait;
3use cnidarium::StateWrite;
4use penumbra_sdk_proto::StateWriteProto as _;
5use penumbra_sdk_shielded_pool::component::AssetRegistry;
6
7use crate::action_handler::ActionHandler;
8use crate::component::{StateReadExt as _, StateWriteExt as _};
9use crate::event;
10use crate::{
11 proposal_state::Outcome, proposal_state::State as ProposalState, ProposalDepositClaim,
12 ProposalNft,
13};
14
15#[async_trait]
16impl ActionHandler for ProposalDepositClaim {
17 type CheckStatelessContext = ();
18 async fn check_stateless(&self, _context: ()) -> Result<()> {
19 Ok(())
21 }
22
23 async fn check_and_execute<S: StateWrite>(&self, mut state: S) -> Result<()> {
24 state.check_proposal_claimable(self.proposal).await?;
26 state
28 .check_proposal_claim_valid_deposit(self.proposal, self.deposit_amount)
29 .await?;
30
31 let ProposalDepositClaim {
32 proposal,
33 deposit_amount: _, outcome: resupplied_outcome,
35 } = self;
36
37 if let Some(ProposalState::Finished { outcome }) = state.proposal_state(*proposal).await? {
43 if *resupplied_outcome != outcome.as_ref().map(|_| ()) {
45 anyhow::bail!(
46 "proposal {} has outcome {:?}, but deposit claim has outcome {:?}",
47 proposal,
48 outcome,
49 resupplied_outcome
50 );
51 }
52
53 state
55 .register_denom(
56 &match &outcome {
57 Outcome::Passed => ProposalNft::passed(*proposal),
58 Outcome::Failed { .. } => ProposalNft::failed(*proposal),
59 Outcome::Slashed { .. } => ProposalNft::slashed(*proposal),
60 }
61 .denom(),
62 )
63 .await;
64
65 state.put_proposal_state(*proposal, ProposalState::Claimed { outcome });
67
68 state.record_proto(event::proposal_deposit_claim(self));
69 } else {
70 anyhow::bail!("proposal {} is not in finished state", proposal);
71 }
72
73 Ok(())
74 }
75}