Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
e99b68e
Initialize blank `futarchy_amm`
metaproph3t Jun 13, 2025
751fcde
Initialize Raydium pool in tests, rename `futarchy_amm` ->
metaproph3t Jun 13, 2025
a651038
Add `initialize_pool` to `shared_liquidity_manager`
metaproph3t Jun 13, 2025
404e944
Add `deposit` to `shared_liquidity_manager`
metaproph3t Jun 14, 2025
b303419
Get Raydium withdraws working on `initialize_proposal_with_liquidity`
metaproph3t Jun 14, 2025
3299ccc
Get splits working on pass market
metaproph3t Jun 14, 2025
a2048cd
Split the full amount of `token_0` and `token_1`
metaproph3t Jun 14, 2025
3aa16a1
Get basic pass/fail LP added
metaproph3t Jun 14, 2025
417da4c
Add custom heap
metaproph3t Jun 14, 2025
5b020c5
Get `deposit_shared_liquidity` fully working
metaproph3t Jun 14, 2025
fabec4c
Start reformatting initializeProposal
metaproph3t Jun 14, 2025
47e8603
Clean up initialize proposal with liquidity
metaproph3t Jun 14, 2025
450e288
Deposit liquidity into `pass_amm`
metaproph3t Jun 14, 2025
a8e4f61
Get proposals initializing
metaproph3t Jun 14, 2025
7b04197
Get nonce working
metaproph3t Jun 14, 2025
9fd606b
Scaffold `withdraw_shared_liquidity`
metaproph3t Jun 14, 2025
d2e725f
Start running into pesky signer error
metaproph3t Jun 14, 2025
315c532
Fix bug with shared accounts
metaproph3t Jun 19, 2025
a81354b
Start on `remove_proposal_liquidity`
metaproph3t Jun 19, 2025
8e18497
Complete `remove_proposal_liquidity`, pending fixes
metaproph3t Jun 19, 2025
65da6d6
Test removing shared liquidity
metaproph3t Jun 19, 2025
825b92f
Fix the LP shares withdrawal issue
metaproph3t Jun 19, 2025
092ab5e
Start on `remove_proposal_liquidity` new pool initialization
metaproph3t Jun 19, 2025
a2a57e2
Get proposal remove working with new AMM!!!!
metaproph3t Jun 19, 2025
a3acf9a
Start cleaning up
metaproph3t Jun 19, 2025
ebda01e
Add `DraftProposal`s
metaproph3t Jun 19, 2025
19c9fbe
Add `stake_to_draft_proposal`
metaproph3t Jun 19, 2025
907027d
Get staking working
metaproph3t Jun 19, 2025
6c1f675
Clean up
metaproph3t Jun 19, 2025
07a985b
Add `unstake_from_draft_proposal`
metaproph3t Jun 19, 2025
4f55da4
Consolidate errors into SharedLiquidityManagerError
metaproph3t Jun 24, 2025
13bebc4
Fix types
metaproph3t Jun 19, 2025
b480cbf
Add comprehensive Rust unit tests for shared_liquidity_manager
metaproph3t Jun 24, 2025
dff1d76
Add unit tests
metaproph3t Jun 19, 2025
996b147
`cargo fmt`
metaproph3t Jun 24, 2025
6cd80ce
`cargo fix --lib -p shared_liquidity_manager`
metaproph3t Jun 24, 2025
150c406
Get tests passing
metaproph3t Jun 25, 2025
3ab959f
Further refine tests
metaproph3t Jun 25, 2025
cab12a4
Start on unit tests for `initialize_proposal_with_liquidity`
metaproph3t Jun 25, 2025
67a1af6
Get more `initialize_proposal_with_liquidity` tests passing
metaproph3t Jun 25, 2025
19a6948
Tests passing
metaproph3t Jun 25, 2025
e257aec
Add a test that proposal initialization fails when it's not a draft
metaproph3t Jun 25, 2025
85b01aa
Add `validate` to `initialize_proposal_with_liquidity`
metaproph3t Jun 25, 2025
69303fe
Update sdk package version
metaproph3t Jun 25, 2025
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
96 changes: 96 additions & 0 deletions .cursor/rules/futarchy-project-overview.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
description:
globs:
alwaysApply: true
---
# Futarchy Project Overview

## Project Structure

This is a Solana-based futarchy platform that implements decision markets and DAO governance. The project consists of multiple Solana programs and a TypeScript SDK.

### Core Programs
- **Autocrat**: DAO governance and proposal management ([programs/autocrat/](mdc:programs/autocrat))
- **AMM**: Automated market maker for trading conditional tokens ([programs/amm/](mdc:programs/amm))
- **Conditional Vault**: Manages conditional tokens for prediction markets ([programs/conditional_vault/](mdc:programs/conditional_vault))
- **Shared Liquidity Manager**: Manages shared liquidity pools for proposals ([programs/shared_liquidity_manager/](mdc:programs/shared_liquidity_manager))
- **Launchpad**: Token launch functionality ([programs/launchpad/](mdc:programs/launchpad))

### SDK Structure
- **v0.3**: Legacy SDK version ([sdk/src/v0.3/](mdc:sdk/src/v0.3))
- **v0.4**: Current SDK version with all latest features ([sdk/src/v0.4/](mdc:sdk/src/v0.4))

### Testing
- **Unit Tests**: Individual instruction tests ([tests/](mdc:tests))
- **Integration Tests**: End-to-end workflow tests ([tests/integration/](mdc:tests/integration))
- **Test Utils**: Common testing utilities ([tests/utils.ts](mdc:tests/utils.ts))

## Development Patterns

### Solana Program Development
- Programs are written in Rust using Anchor framework
- Each program has its own `Cargo.toml` and `src/` directory
- Programs follow Anchor's instruction-based architecture

### Testing Patterns
- Tests use `bankrun` for fast, deterministic testing
- Complex transactions use lookup tables and `TransactionMessage` for large account lists
- Tests often require full proposal lifecycle setup (draft → stake → initialize → crank → finalize).
We generally do that setup in `before` and `beforeEach` blocks

### SDK Development
- TypeScript SDK provides client interfaces for all programs
- SDK handles PDA derivation, instruction building, and transaction management
- Versioned SDKs maintain backward compatibility

## Key Concepts

### Futarchy
- Governance through markets
- Proposals create conditional tokens (PASS/FAIL)
- Market prices determine proposal outcomes

### Conditional Tokens
- Represent outcomes of events (e.g., "Will proposal X pass?")
- Can be split, merged, and redeemed based on outcomes
- Used for prediction market trading

### Shared Liquidity
- Pools that provide liquidity on both spot markets and decision markets
- Managed through the Shared Liquidity Manager program

## Common Development Tasks

### Adding New Instructions
1. Add instruction to Rust program in `programs/[program]/src/instructions/`
2. Update client methods in SDK
3. Add unit tests in `tests/[program]/unit/`
4. Add integration tests if needed

### Running Tests
```bash
# Run all tests
anchor test

# Run specific test file
anchor test tests/sharedLiquidityManager/unit/removeProposalLiquidity.test.ts

# Skip build for faster iteration, you should run this if you haven't changed a rust file
anchor test --skip-build
```

### Building Programs
```bash
# Build all programs
anchor build

# Build specific program
anchor build --program-name [program_name]
```

## File References
- Main configuration: [Anchor.toml](mdc:Anchor.toml)
- SDK entry point: [sdk/src/index.ts](mdc:sdk/src/index.ts)
- Test utilities: [tests/utils.ts](mdc:tests/utils.ts)
- Example test: @tests/launchpad/unit/refund.test.ts

7 changes: 4 additions & 3 deletions Anchor.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ amm = "AMMyu265tkBpRW21iGQxKGLaves3gKm2JcMUqfXNSpqD"
autocrat = "autowMzCbM29YXMgVG3T62Hkgo7RcyrvgQQkd54fDQL"
autocrat_migrator = "MigRDW6uxyNMDBD8fX2njCRyJC4YZk2Rx9pDUZiAESt"
conditional_vault = "VLTX1ishMBbcX3rdBWGssxawAo1Q2X2qxYFYqiGodVg"
shared_liquidity_manager = "EoJc1PYxZbnCjszampLcwJGYcB5Md47jM4oSQacRtD4d"
launchpad = "AfJJJ5UqxhBKoE3grkKAZZsoXDE9kncbMKvqSHGsCNrE"
optimistic_timelock = "tiME1hz9F5C5ZecbvE5z6Msjy8PKfTqo1UuRYXfndKF"

Expand All @@ -20,13 +21,13 @@ cluster = "Localnet"
wallet = "~/.config/solana/id.json"

[scripts]
test = "npx mocha --import=tsx tests/main.test.ts"
add-v03-metadata = "yarn run tsx scripts/addV03Metadata.ts"
initialize-launch = "yarn run tsx scripts/initializeLaunch.ts"
add-v04-metadata = "yarn run tsx scripts/addV04Metadata.ts"
create-proposal = "yarn run tsx scripts/createProposal.ts"
create-v04-dao = "yarn run tsx scripts/createV04DAO.ts"
create-v04-proposal = "yarn run tsx scripts/createV04Proposal.ts"
add-v04-metadata = "yarn run tsx scripts/addV04Metadata.ts"
initialize-launch = "yarn run tsx scripts/initializeLaunch.ts"
test = "npx mocha --import=tsx --bail tests/main.test.ts"

[test]
startup_wait = 5000
Expand Down
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"dependencies": {
"@coral-xyz/anchor": "0.29.0",
"@inquirer/prompts": "^7.3.3",
"@metadaoproject/futarchy": "0.4.0-alpha.73",
"@metadaoproject/futarchy": "0.4.0-alpha.74",
"@metaplex-foundation/mpl-token-metadata": "^3.2.0",
"@metaplex-foundation/umi": "^0.9.1",
"@metaplex-foundation/umi-bundle-defaults": "^0.9.1",
Expand Down
4 changes: 2 additions & 2 deletions programs/amm/src/instructions/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ pub struct AddOrRemoveLiquidity<'info> {
pub user_lp_account: Box<Account<'info, TokenAccount>>,
#[account(
mut,
token::mint = amm.base_mint,
// token::mint = amm.base_mint,
token::authority = user,
)]
pub user_base_account: Box<Account<'info, TokenAccount>>,
#[account(
mut,
token::mint = amm.quote_mint,
// token::mint = amm.quote_mint,
token::authority = user,
)]
pub user_quote_account: Box<Account<'info, TokenAccount>>,
Expand Down
3 changes: 3 additions & 0 deletions programs/amm/src/instructions/create_amm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ impl CreateAmm<'_> {
),

seq_num: 0,

vault_ata_base: vault_ata_base.key(),
vault_ata_quote: vault_ata_quote.key(),
});

let clock = Clock::get()?;
Expand Down
9 changes: 8 additions & 1 deletion programs/amm/src/state/amm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ pub struct Amm {
pub oracle: TwapOracle,

pub seq_num: u64,

pub vault_ata_base: Pubkey,
pub vault_ata_quote: Pubkey,
}

impl Amm {
Expand Down Expand Up @@ -171,7 +174,11 @@ impl Amm {
pub fn get_twap(&self) -> Result<u128> {
let start_slot = self.created_at_slot + self.oracle.start_delay_slots;

require_gt!(self.oracle.last_updated_slot, start_slot, AmmError::NoSlotsPassed);
require_gt!(
self.oracle.last_updated_slot,
start_slot,
AmmError::NoSlotsPassed
);
let slots_passed = (self.oracle.last_updated_slot - start_slot) as u128;

require_neq!(slots_passed, 0, AmmError::NoSlotsPassed);
Expand Down
6 changes: 4 additions & 2 deletions programs/autocrat/src/instructions/initialize_proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub struct InitializeProposalParams {
pub struct InitializeProposal<'info> {
#[account(
init,
payer = proposer,
payer = payer,
space = 2000,
seeds = [b"proposal", proposer.key().as_ref(), &args.nonce.to_le_bytes()],
bump
Expand Down Expand Up @@ -78,8 +78,9 @@ pub struct InitializeProposal<'info> {
associated_token::authority = dao.treasury,
)]
pub fail_lp_vault_account: Account<'info, TokenAccount>,
#[account(mut)]
pub proposer: Signer<'info>,
#[account(mut)]
pub payer: Signer<'info>,
pub token_program: Program<'info, Token>,
pub system_program: Program<'info, System>,
}
Expand Down Expand Up @@ -136,6 +137,7 @@ impl InitializeProposal<'_> {
pass_lp_vault_account,
fail_lp_vault_account,
proposer,
payer: _,
token_program,
system_program: _,
event_authority: _,
Expand Down
8 changes: 7 additions & 1 deletion programs/autocrat/src/state/proposal.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
use super::*;

#[derive(Clone, Copy, AnchorSerialize, AnchorDeserialize, PartialEq, Eq)]
#[derive(Clone, Copy, AnchorSerialize, AnchorDeserialize, PartialEq, Eq, Debug)]
pub enum ProposalState {
Pending,
Passed,
Failed,
Executed,
}

impl std::fmt::Display for ProposalState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}

#[derive(Clone, AnchorSerialize, AnchorDeserialize, Debug, PartialEq, Eq)]
pub struct ProposalAccount {
pub pubkey: Pubkey,
Expand Down
2 changes: 1 addition & 1 deletion programs/launchpad/src/instructions/complete_launch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use raydium_cpmm_cpi::{

use autocrat::program::Autocrat;
use autocrat::InitializeDaoParams;
use autocrat::{DAY_IN_SLOTS};
use autocrat::DAY_IN_SLOTS;

pub const PRICE_SCALE: u128 = 1_000_000_000_000;

Expand Down
6 changes: 1 addition & 5 deletions programs/launchpad/src/instructions/initialize_launch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ pub struct InitializeLaunch<'info> {

impl InitializeLaunch<'_> {
pub fn validate(&self, args: &InitializeLaunchArgs) -> Result<()> {

#[cfg(not(feature = "devnet"))]
require_gte!(
args.seconds_for_launch,
Expand All @@ -109,10 +108,7 @@ impl InitializeLaunch<'_> {
LaunchpadError::FreezeAuthoritySet
);

require!(
self.token_mint.supply == 0,
LaunchpadError::SupplyNonZero
);
require!(self.token_mint.supply == 0, LaunchpadError::SupplyNonZero);

#[cfg(feature = "production")]
{
Expand Down
32 changes: 32 additions & 0 deletions programs/shared_liquidity_manager/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[package]
name = "shared_liquidity_manager"
version = "0.1.0"
description = "Created with Anchor"
edition = "2021"

[lib]
crate-type = ["cdylib", "lib"]
name = "shared_liquidity_manager"

[features]
no-entrypoint = []
no-idl = []
no-log-ix-name = []
cpi = ["no-entrypoint"]
default = ["custom-heap"]
custom-heap = []

[dependencies]
anchor-lang = "0.29.0"
autocrat = { path = "../autocrat", features = ["cpi"] }
amm = { path = "../amm", features = ["cpi"] }
conditional_vault = { path = "../conditional_vault", features = ["cpi"] }
raydium-cpmm-cpi = { git = "https://github.com/raydium-io/raydium-cpi", package = "raydium-cpmm-cpi", branch = "anchor-0.29.0" }
spl-memo = "=4.0.0"
solana-program = "=1.17.14"
spl-token = "=4.0.0"
ahash = "=0.8.6"
solana-security-txt = "1.1.1"
anchor-spl = "^0.29.0"


2 changes: 2 additions & 0 deletions programs/shared_liquidity_manager/Xargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []
43 changes: 43 additions & 0 deletions programs/shared_liquidity_manager/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use anchor_lang::prelude::*;

#[error_code]
pub enum SharedLiquidityManagerError {
#[msg("Insufficient stake amount")]
InsufficientStake,
#[msg("Proposal is not finalized")]
ProposalNotFinalized,
#[msg("No LP tokens to remove from AMM")]
NoLpTokensToRemove,
#[msg("No tokens received from AMM removal")]
NoTokensFromAmm,
#[msg("Insufficient reserves returned to spot AMM (less than 99.5%)")]
InsufficientReservesReturned,
#[msg("Pool is currently being used by an active proposal")]
PoolInUse,
#[msg("User does not have enough LP shares to withdraw")]
InsufficientLpShares,
#[msg("Slippage exceeded minimum token amounts")]
SlippageExceeded,
#[msg("No LP tokens in pool's LP token account")]
NoLpTokensInPool,
#[msg("Not enough LP tokens to provide liquidity to proposal")]
NotEnoughLpTokens,
#[msg("Insufficient funds")]
InsufficientFunds,
#[msg("No active proposal")]
NoActiveProposal,
#[msg("Proposal is not in draft status")]
ProposalNotInDraftStatus,
#[msg("Proposal already active")]
ProposalAlreadyActive,
#[msg("AMM already has liquidity")]
AmmAlreadyHasLiquidity,
#[msg("Question already resolved")]
QuestionAlreadyResolved,
}


// 1 PLTR = 100 USDC
// We put 1 PLTR in, & 100 USDC in
// I get 100 PLTR-DOWN and you get 100 PLTR-UP.
// If PLTR goes to 10 USDC, I get 90 USDC
Loading
Loading