Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Anchor.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ v07-approve-points-based = "yarn run tsx scripts/v0.7/pointsBased/approveWithPoi
v07-close-launch = "yarn run tsx scripts/v0.7/closeLaunch.ts"
v07-initialize-performance-package = "yarn run tsx scripts/v0.7/initializePerformancePackage.ts"
v07-claim-launch-additional-tokens = "yarn run tsx scripts/v0.7/claimLaunchAdditionalTokens.ts"
v07-remove-proposal = "yarn run tsx scripts/v0.7/removeProposal.ts"

[test]
startup_wait = 5000
Expand Down
8 changes: 8 additions & 0 deletions programs/futarchy/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,14 @@ pub struct SponsorProposalEvent {
pub team_address: Pubkey,
}

#[event]
pub struct RemoveProposalEvent {
pub common: CommonFields,
pub proposal: Pubkey,
pub dao: Pubkey,
pub admin: Pubkey,
}

#[event]
pub struct CollectMeteoraDammFeesEvent {
pub common: CommonFields,
Expand Down
51 changes: 51 additions & 0 deletions programs/futarchy/src/instructions/admin_remove_proposal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use super::*;

pub mod admin {
use anchor_lang::prelude::declare_id;
declare_id!("tSTp6B6kE9o6ZaTmHm2ZwnJBBtgd3x112tapxFhmBEQ");
}

#[derive(Accounts)]
#[event_cpi]
pub struct AdminRemoveProposal<'info> {
#[account(mut, has_one = dao)]
pub proposal: Box<Account<'info, Proposal>>,
#[account(mut)]
pub dao: Box<Account<'info, Dao>>,
#[account(mut)]
pub admin: Signer<'info>,
}

impl AdminRemoveProposal<'_> {
pub fn validate(&self) -> Result<()> {
#[cfg(feature = "production")]
require_keys_eq!(self.admin.key(), admin::ID, FutarchyError::InvalidAdmin);

Comment thread
pileks marked this conversation as resolved.
// TODO: See how we'd handle cancelling a proposal that has already been launched (in Pending state)
require!(
matches!(self.proposal.state, ProposalState::Draft { .. }),
FutarchyError::ProposalNotInDraftState
);

Ok(())
}

pub fn handle(ctx: Context<Self>) -> Result<()> {
let proposal = &mut ctx.accounts.proposal;
let dao = &mut ctx.accounts.dao;

proposal.state = ProposalState::Removed;

dao.seq_num += 1;
let clock = Clock::get()?;

emit_cpi!(RemoveProposalEvent {
common: CommonFields::new(&clock, dao.seq_num),
proposal: proposal.key(),
dao: dao.key(),
admin: ctx.accounts.admin.key(),
});

Ok(())
}
}
2 changes: 2 additions & 0 deletions programs/futarchy/src/instructions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::*;

pub mod admin_approve_execute_multisig_proposal;
pub mod admin_remove_proposal;
pub mod collect_fees;
pub mod collect_meteora_damm_fees;
pub mod conditional_swap;
Expand All @@ -18,6 +19,7 @@ pub mod update_dao;
pub mod withdraw_liquidity;

pub use admin_approve_execute_multisig_proposal::*;
pub use admin_remove_proposal::*;
pub use collect_fees::*;
pub use collect_meteora_damm_fees::*;
pub use conditional_swap::*;
Expand Down
5 changes: 1 addition & 4 deletions programs/futarchy/src/instructions/withdraw_liquidity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,7 @@ impl WithdrawLiquidity<'_> {
// TODO: check that pool is already in right state
unreachable!();
};
spot.get_base_and_quote_withdrawable(
liquidity_to_withdraw as u64,
total_liquidity as u64,
)
spot.get_base_and_quote_withdrawable(liquidity_to_withdraw, total_liquidity)
};

require_gte!(
Expand Down
5 changes: 5 additions & 0 deletions programs/futarchy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,9 @@ pub mod futarchy {
) -> Result<()> {
AdminApproveExecuteMultisigProposal::handle(ctx)
}

#[access_control(ctx.accounts.validate())]
pub fn admin_remove_proposal(ctx: Context<AdminRemoveProposal>) -> Result<()> {
AdminRemoveProposal::handle(ctx)
}
}
12 changes: 6 additions & 6 deletions programs/futarchy/src/state/futarchy_amm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,8 +583,8 @@ impl Pool {
/// Get the number of base and quote tokens withdrawable from a position
pub fn get_base_and_quote_withdrawable(
&self,
lp_tokens: u64,
lp_total_supply: u64,
lp_tokens: u128,
lp_total_supply: u128,
) -> (u64, u64) {
(
self.get_base_withdrawable(lp_tokens, lp_total_supply),
Expand All @@ -593,14 +593,14 @@ impl Pool {
}

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

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

Expand Down
1 change: 1 addition & 0 deletions programs/futarchy/src/state/proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub enum ProposalState {
Pending,
Passed,
Failed,
Removed,
}

impl std::fmt::Display for ProposalState {
Expand Down
44 changes: 44 additions & 0 deletions scripts/v0.7/removeProposal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as anchor from "@coral-xyz/anchor";
import {
CONDITIONAL_VAULT_PROGRAM_ID,
FUTARCHY_PROGRAM_ID,
FutarchyClient,
} from "@metadaoproject/futarchy/v0.7";
import { PublicKey } from "@solana/web3.js";

// Set the proposal address before running the script
const proposal = new PublicKey("");

const provider = anchor.AnchorProvider.env();

// Payer MUST be the admin signer - tSTp6B6kE9o6ZaTmHm2ZwnJBBtgd3x112tapxFhmBEQ
const payer = provider.wallet["payer"];

const futarchy: FutarchyClient = new FutarchyClient(
provider,
FUTARCHY_PROGRAM_ID,
CONDITIONAL_VAULT_PROGRAM_ID,
[],
);

export const removeProposal = async () => {
// Fetch the proposal to get the DAO address
const proposalAccount = await futarchy.getProposal(proposal);

console.log(`Removing proposal at address: ${proposal.toBase58()}`);
console.log(`DAO: ${proposalAccount.dao.toBase58()}`);
console.log(`Current state: ${JSON.stringify(proposalAccount.state)}`);

const tx = await futarchy.autocrat.methods
.adminRemoveProposal()
.accounts({
proposal,
dao: proposalAccount.dao,
admin: payer.publicKey,
})
.rpc();

console.log(`Proposal removed successfully. Signature: ${tx}`);
};

removeProposal().catch(console.error);
122 changes: 122 additions & 0 deletions sdk/src/v0.7/types/futarchy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,37 @@ export type Futarchy = {
];
args: [];
},
{
name: "adminRemoveProposal";
accounts: [
{
name: "proposal";
isMut: true;
isSigner: false;
},
{
name: "dao";
isMut: true;
isSigner: false;
},
{
name: "admin";
isMut: true;
isSigner: true;
},
{
name: "eventAuthority";
isMut: false;
isSigner: false;
},
{
name: "program";
isMut: false;
isSigner: false;
},
];
args: [];
},
];
accounts: [
{
Expand Down Expand Up @@ -2029,6 +2060,9 @@ export type Futarchy = {
{
name: "Failed";
},
{
name: "Removed";
},
];
};
},
Expand Down Expand Up @@ -2751,6 +2785,33 @@ export type Futarchy = {
},
];
},
{
name: "RemoveProposalEvent";
fields: [
{
name: "common";
type: {
defined: "CommonFields";
};
index: false;
},
{
name: "proposal";
type: "publicKey";
index: false;
},
{
name: "dao";
type: "publicKey";
index: false;
},
{
name: "admin";
type: "publicKey";
index: false;
},
];
},
{
name: "CollectMeteoraDammFeesEvent";
fields: [
Expand Down Expand Up @@ -4221,6 +4282,37 @@ export const IDL: Futarchy = {
],
args: [],
},
{
name: "adminRemoveProposal",
accounts: [
{
name: "proposal",
isMut: true,
isSigner: false,
},
{
name: "dao",
isMut: true,
isSigner: false,
},
{
name: "admin",
isMut: true,
isSigner: true,
},
{
name: "eventAuthority",
isMut: false,
isSigner: false,
},
{
name: "program",
isMut: false,
isSigner: false,
},
],
args: [],
},
],
accounts: [
{
Expand Down Expand Up @@ -5019,6 +5111,9 @@ export const IDL: Futarchy = {
{
name: "Failed",
},
{
name: "Removed",
},
],
},
},
Expand Down Expand Up @@ -5741,6 +5836,33 @@ export const IDL: Futarchy = {
},
],
},
{
name: "RemoveProposalEvent",
fields: [
{
name: "common",
type: {
defined: "CommonFields",
},
index: false,
},
{
name: "proposal",
type: "publicKey",
index: false,
},
{
name: "dao",
type: "publicKey",
index: false,
},
{
name: "admin",
type: "publicKey",
index: false,
},
],
},
{
name: "CollectMeteoraDammFeesEvent",
fields: [
Expand Down
2 changes: 2 additions & 0 deletions tests/futarchy/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import executeSpendingLimitChange from "./unit/executeSpendingLimitChange.test.j

import collectMeteoraDammFees from "./unit/collectMeteoraDammFees.test.js";
import adminApproveProposal from "./unit/adminApproveExecuteMultisigProposal.test.js";
import adminRemoveProposal from "./unit/adminRemoveProposal.test.js";

import { PublicKey } from "@solana/web3.js";
import {
Expand Down Expand Up @@ -55,6 +56,7 @@ export default function suite() {
describe("#collect_meteora_damm_fees", collectMeteoraDammFees);

describe("#admin_approve_proposal", adminApproveProposal);
describe("#admin_remove_proposal", adminRemoveProposal);
// describe("full proposal", fullProposal);
// describe("proposal with a squads batch tx", proposalBatchTx);
describe("futarchy amm", futarchyAmm);
Expand Down
Loading
Loading