Skip to content

Commit 1fe350a

Browse files
authored
Remove proposal (#415)
* fix up messy integer handling * removes proposal when called by admin * add comment
1 parent d251475 commit 1fe350a

12 files changed

Lines changed: 505 additions & 10 deletions

File tree

Anchor.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ v07-approve-points-based = "yarn run tsx scripts/v0.7/pointsBased/approveWithPoi
5959
v07-close-launch = "yarn run tsx scripts/v0.7/closeLaunch.ts"
6060
v07-initialize-performance-package = "yarn run tsx scripts/v0.7/initializePerformancePackage.ts"
6161
v07-claim-launch-additional-tokens = "yarn run tsx scripts/v0.7/claimLaunchAdditionalTokens.ts"
62+
v07-remove-proposal = "yarn run tsx scripts/v0.7/removeProposal.ts"
6263

6364
[test]
6465
startup_wait = 5000

programs/futarchy/src/events.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,14 @@ pub struct SponsorProposalEvent {
191191
pub team_address: Pubkey,
192192
}
193193

194+
#[event]
195+
pub struct RemoveProposalEvent {
196+
pub common: CommonFields,
197+
pub proposal: Pubkey,
198+
pub dao: Pubkey,
199+
pub admin: Pubkey,
200+
}
201+
194202
#[event]
195203
pub struct CollectMeteoraDammFeesEvent {
196204
pub common: CommonFields,
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use super::*;
2+
3+
pub mod admin {
4+
use anchor_lang::prelude::declare_id;
5+
declare_id!("tSTp6B6kE9o6ZaTmHm2ZwnJBBtgd3x112tapxFhmBEQ");
6+
}
7+
8+
#[derive(Accounts)]
9+
#[event_cpi]
10+
pub struct AdminRemoveProposal<'info> {
11+
#[account(mut, has_one = dao)]
12+
pub proposal: Box<Account<'info, Proposal>>,
13+
#[account(mut)]
14+
pub dao: Box<Account<'info, Dao>>,
15+
#[account(mut)]
16+
pub admin: Signer<'info>,
17+
}
18+
19+
impl AdminRemoveProposal<'_> {
20+
pub fn validate(&self) -> Result<()> {
21+
#[cfg(feature = "production")]
22+
require_keys_eq!(self.admin.key(), admin::ID, FutarchyError::InvalidAdmin);
23+
24+
// TODO: See how we'd handle cancelling a proposal that has already been launched (in Pending state)
25+
require!(
26+
matches!(self.proposal.state, ProposalState::Draft { .. }),
27+
FutarchyError::ProposalNotInDraftState
28+
);
29+
30+
Ok(())
31+
}
32+
33+
pub fn handle(ctx: Context<Self>) -> Result<()> {
34+
let proposal = &mut ctx.accounts.proposal;
35+
let dao = &mut ctx.accounts.dao;
36+
37+
proposal.state = ProposalState::Removed;
38+
39+
dao.seq_num += 1;
40+
let clock = Clock::get()?;
41+
42+
emit_cpi!(RemoveProposalEvent {
43+
common: CommonFields::new(&clock, dao.seq_num),
44+
proposal: proposal.key(),
45+
dao: dao.key(),
46+
admin: ctx.accounts.admin.key(),
47+
});
48+
49+
Ok(())
50+
}
51+
}

programs/futarchy/src/instructions/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::*;
22

33
pub mod admin_approve_execute_multisig_proposal;
4+
pub mod admin_remove_proposal;
45
pub mod collect_fees;
56
pub mod collect_meteora_damm_fees;
67
pub mod conditional_swap;
@@ -18,6 +19,7 @@ pub mod update_dao;
1819
pub mod withdraw_liquidity;
1920

2021
pub use admin_approve_execute_multisig_proposal::*;
22+
pub use admin_remove_proposal::*;
2123
pub use collect_fees::*;
2224
pub use collect_meteora_damm_fees::*;
2325
pub use conditional_swap::*;

programs/futarchy/src/instructions/withdraw_liquidity.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,7 @@ impl WithdrawLiquidity<'_> {
9696
// TODO: check that pool is already in right state
9797
unreachable!();
9898
};
99-
spot.get_base_and_quote_withdrawable(
100-
liquidity_to_withdraw as u64,
101-
total_liquidity as u64,
102-
)
99+
spot.get_base_and_quote_withdrawable(liquidity_to_withdraw, total_liquidity)
103100
};
104101

105102
require_gte!(

programs/futarchy/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,9 @@ pub mod futarchy {
154154
) -> Result<()> {
155155
AdminApproveExecuteMultisigProposal::handle(ctx)
156156
}
157+
158+
#[access_control(ctx.accounts.validate())]
159+
pub fn admin_remove_proposal(ctx: Context<AdminRemoveProposal>) -> Result<()> {
160+
AdminRemoveProposal::handle(ctx)
161+
}
157162
}

programs/futarchy/src/state/futarchy_amm.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -583,8 +583,8 @@ impl Pool {
583583
/// Get the number of base and quote tokens withdrawable from a position
584584
pub fn get_base_and_quote_withdrawable(
585585
&self,
586-
lp_tokens: u64,
587-
lp_total_supply: u64,
586+
lp_tokens: u128,
587+
lp_total_supply: u128,
588588
) -> (u64, u64) {
589589
(
590590
self.get_base_withdrawable(lp_tokens, lp_total_supply),
@@ -593,14 +593,14 @@ impl Pool {
593593
}
594594

595595
/// Get the number of base tokens withdrawable from a position
596-
pub fn get_base_withdrawable(&self, lp_tokens: u64, lp_total_supply: u64) -> u64 {
596+
pub fn get_base_withdrawable(&self, lp_tokens: u128, lp_total_supply: u128) -> u64 {
597597
// must fit back into u64 since `lp_tokens` <= `lp_total_supply`
598-
((lp_tokens as u128 * self.base_reserves as u128) / lp_total_supply as u128) as u64
598+
((lp_tokens * self.base_reserves as u128) / lp_total_supply) as u64
599599
}
600600

601601
/// Get the number of quote tokens withdrawable from a position
602-
pub fn get_quote_withdrawable(&self, lp_tokens: u64, lp_total_supply: u64) -> u64 {
603-
((lp_tokens as u128 * self.quote_reserves as u128) / lp_total_supply as u128) as u64
602+
pub fn get_quote_withdrawable(&self, lp_tokens: u128, lp_total_supply: u128) -> u64 {
603+
((lp_tokens * self.quote_reserves as u128) / lp_total_supply) as u64
604604
}
605605
}
606606

programs/futarchy/src/state/proposal.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub enum ProposalState {
66
Pending,
77
Passed,
88
Failed,
9+
Removed,
910
}
1011

1112
impl std::fmt::Display for ProposalState {

scripts/v0.7/removeProposal.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import * as anchor from "@coral-xyz/anchor";
2+
import {
3+
CONDITIONAL_VAULT_PROGRAM_ID,
4+
FUTARCHY_PROGRAM_ID,
5+
FutarchyClient,
6+
} from "@metadaoproject/futarchy/v0.7";
7+
import { PublicKey } from "@solana/web3.js";
8+
9+
// Set the proposal address before running the script
10+
const proposal = new PublicKey("");
11+
12+
const provider = anchor.AnchorProvider.env();
13+
14+
// Payer MUST be the admin signer - tSTp6B6kE9o6ZaTmHm2ZwnJBBtgd3x112tapxFhmBEQ
15+
const payer = provider.wallet["payer"];
16+
17+
const futarchy: FutarchyClient = new FutarchyClient(
18+
provider,
19+
FUTARCHY_PROGRAM_ID,
20+
CONDITIONAL_VAULT_PROGRAM_ID,
21+
[],
22+
);
23+
24+
export const removeProposal = async () => {
25+
// Fetch the proposal to get the DAO address
26+
const proposalAccount = await futarchy.getProposal(proposal);
27+
28+
console.log(`Removing proposal at address: ${proposal.toBase58()}`);
29+
console.log(`DAO: ${proposalAccount.dao.toBase58()}`);
30+
console.log(`Current state: ${JSON.stringify(proposalAccount.state)}`);
31+
32+
const tx = await futarchy.autocrat.methods
33+
.adminRemoveProposal()
34+
.accounts({
35+
proposal,
36+
dao: proposalAccount.dao,
37+
admin: payer.publicKey,
38+
})
39+
.rpc();
40+
41+
console.log(`Proposal removed successfully. Signature: ${tx}`);
42+
};
43+
44+
removeProposal().catch(console.error);

sdk/src/v0.7/types/futarchy.ts

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,37 @@ export type Futarchy = {
12311231
];
12321232
args: [];
12331233
},
1234+
{
1235+
name: "adminRemoveProposal";
1236+
accounts: [
1237+
{
1238+
name: "proposal";
1239+
isMut: true;
1240+
isSigner: false;
1241+
},
1242+
{
1243+
name: "dao";
1244+
isMut: true;
1245+
isSigner: false;
1246+
},
1247+
{
1248+
name: "admin";
1249+
isMut: true;
1250+
isSigner: true;
1251+
},
1252+
{
1253+
name: "eventAuthority";
1254+
isMut: false;
1255+
isSigner: false;
1256+
},
1257+
{
1258+
name: "program";
1259+
isMut: false;
1260+
isSigner: false;
1261+
},
1262+
];
1263+
args: [];
1264+
},
12341265
];
12351266
accounts: [
12361267
{
@@ -2029,6 +2060,9 @@ export type Futarchy = {
20292060
{
20302061
name: "Failed";
20312062
},
2063+
{
2064+
name: "Removed";
2065+
},
20322066
];
20332067
};
20342068
},
@@ -2751,6 +2785,33 @@ export type Futarchy = {
27512785
},
27522786
];
27532787
},
2788+
{
2789+
name: "RemoveProposalEvent";
2790+
fields: [
2791+
{
2792+
name: "common";
2793+
type: {
2794+
defined: "CommonFields";
2795+
};
2796+
index: false;
2797+
},
2798+
{
2799+
name: "proposal";
2800+
type: "publicKey";
2801+
index: false;
2802+
},
2803+
{
2804+
name: "dao";
2805+
type: "publicKey";
2806+
index: false;
2807+
},
2808+
{
2809+
name: "admin";
2810+
type: "publicKey";
2811+
index: false;
2812+
},
2813+
];
2814+
},
27542815
{
27552816
name: "CollectMeteoraDammFeesEvent";
27562817
fields: [
@@ -4221,6 +4282,37 @@ export const IDL: Futarchy = {
42214282
],
42224283
args: [],
42234284
},
4285+
{
4286+
name: "adminRemoveProposal",
4287+
accounts: [
4288+
{
4289+
name: "proposal",
4290+
isMut: true,
4291+
isSigner: false,
4292+
},
4293+
{
4294+
name: "dao",
4295+
isMut: true,
4296+
isSigner: false,
4297+
},
4298+
{
4299+
name: "admin",
4300+
isMut: true,
4301+
isSigner: true,
4302+
},
4303+
{
4304+
name: "eventAuthority",
4305+
isMut: false,
4306+
isSigner: false,
4307+
},
4308+
{
4309+
name: "program",
4310+
isMut: false,
4311+
isSigner: false,
4312+
},
4313+
],
4314+
args: [],
4315+
},
42244316
],
42254317
accounts: [
42264318
{
@@ -5019,6 +5111,9 @@ export const IDL: Futarchy = {
50195111
{
50205112
name: "Failed",
50215113
},
5114+
{
5115+
name: "Removed",
5116+
},
50225117
],
50235118
},
50245119
},
@@ -5741,6 +5836,33 @@ export const IDL: Futarchy = {
57415836
},
57425837
],
57435838
},
5839+
{
5840+
name: "RemoveProposalEvent",
5841+
fields: [
5842+
{
5843+
name: "common",
5844+
type: {
5845+
defined: "CommonFields",
5846+
},
5847+
index: false,
5848+
},
5849+
{
5850+
name: "proposal",
5851+
type: "publicKey",
5852+
index: false,
5853+
},
5854+
{
5855+
name: "dao",
5856+
type: "publicKey",
5857+
index: false,
5858+
},
5859+
{
5860+
name: "admin",
5861+
type: "publicKey",
5862+
index: false,
5863+
},
5864+
],
5865+
},
57445866
{
57455867
name: "CollectMeteoraDammFeesEvent",
57465868
fields: [

0 commit comments

Comments
 (0)