typeAmm={ accounts:[ { name:"amm"; type:{ fields:[ {name:"bump";type:"u8"}, {name:"createdAtSlot";type:"u64"}, {name:"lpMint";type:"publicKey"}, {name:"baseMint";type:"publicKey"}, {name:"quoteMint";type:"publicKey"}, {name:"baseMintDecimals";type:"u8"}, {name:"quoteMintDecimals";type:"u8"}, {name:"baseAmount";type:"u64"}, {name:"quoteAmount";type:"u64"}, {name:"oracle";type:{defined:"TwapOracle"}}, ]; kind:"struct"; }; }, ]; errors:[ { code:6000; msg:"Can't get a TWAP before some observations have been stored"; name:"NoSlotsPassed"; }, { code:6001; msg:"Can't swap through a pool without token reserves on either side"; name:"NoReserves"; }, { code:6002; msg:"Input token amount is too large for a swap, causes overflow"; name:"InputAmountOverflow"; }, { code:6003; msg:"Add liquidity calculation error"; name:"AddLiquidityCalculationError"; }, { code:6004; msg:"Error in decimal scale conversion"; name:"DecimalScaleError"; }, { code:6005; msg:"You can't create an AMM pool where the token mints are the same"; name:"SameTokenMints"; }, { code:6006; msg:"A user wouldn't have gotten back their `output_amount_min`, reverting"; name:"SwapSlippageExceeded"; }, { code:6007; msg:"The user had insufficient balance to do this"; name:"InsufficientBalance"; }, { code:6008; msg:"Must remove a non-zero amount of liquidity"; name:"ZeroLiquidityRemove"; }, { code:6009; msg:"Cannot add liquidity with 0 tokens on either side"; name:"ZeroLiquidityToAdd"; }, { code:6010; msg:"Must specify a non-zero `min_lp_tokens` when adding to an existing pool"; name:"ZeroMinLpTokens"; }, { code:6011; msg:"LP wouldn't have gotten back `lp_token_min`"; name:"AddLiquiditySlippageExceeded"; }, { code:6012; msg:"LP would have spent more than `max_base_amount`"; name:"AddLiquidityMaxBaseExceeded"; }, { code:6013; msg:"`quote_amount` must be greater than 100000000 when initializing a pool"; name:"InsufficientQuoteAmount"; }, { code:6014; msg:"Users must swap a non-zero amount"; name:"ZeroSwapAmount"; }, { code:6015; msg:"K should always be increasing"; name:"ConstantProductInvariantFailed"; }, { code:6016; msg:"Casting has caused an overflow"; name:"CastingOverflow"; }, ]; instructions:[ { accounts:[ {isMut:true;isSigner:true;name:"user"}, {isMut:true;isSigner:false;name:"amm"}, {isMut:true;isSigner:false;name:"lpMint"}, {isMut:false;isSigner:false;name:"baseMint"}, {isMut:false;isSigner:false;name:"quoteMint"}, {isMut:true;isSigner:false;name:"vaultAtaBase"}, {isMut:true;isSigner:false;name:"vaultAtaQuote"}, {isMut:false;isSigner:false;name:"associatedTokenProgram"}, {isMut:false;isSigner:false;name:"tokenProgram"}, {isMut:false;isSigner:false;name:"systemProgram"}, ]; args:[{name:"args";type:{defined:"CreateAmmArgs"}}]; name:"createAmm"; }, { accounts:[ {isMut:true;isSigner:true;name:"user"}, {isMut:true;isSigner:false;name:"amm"}, {isMut:true;isSigner:false;name:"lpMint"}, {isMut:true;isSigner:false;name:"userLpAccount"}, {isMut:true;isSigner:false;name:"userBaseAccount"}, {isMut:true;isSigner:false;name:"userQuoteAccount"}, {isMut:true;isSigner:false;name:"vaultAtaBase"}, {isMut:true;isSigner:false;name:"vaultAtaQuote"}, {isMut:false;isSigner:false;name:"tokenProgram"}, ]; args:[{name:"args";type:{defined:"AddLiquidityArgs"}}]; name:"addLiquidity"; }, { accounts:[ {isMut:true;isSigner:true;name:"user"}, {isMut:true;isSigner:false;name:"amm"}, {isMut:true;isSigner:false;name:"lpMint"}, {isMut:true;isSigner:false;name:"userLpAccount"}, {isMut:true;isSigner:false;name:"userBaseAccount"}, {isMut:true;isSigner:false;name:"userQuoteAccount"}, {isMut:true;isSigner:false;name:"vaultAtaBase"}, {isMut:true;isSigner:false;name:"vaultAtaQuote"}, {isMut:false;isSigner:false;name:"tokenProgram"}, ]; args:[{name:"args";type:{defined:"RemoveLiquidityArgs"}}]; name:"removeLiquidity"; }, { accounts:[ {isMut:true;isSigner:true;name:"user"}, {isMut:true;isSigner:false;name:"amm"}, {isMut:true;isSigner:false;name:"userBaseAccount"}, {isMut:true;isSigner:false;name:"userQuoteAccount"}, {isMut:true;isSigner:false;name:"vaultAtaBase"}, {isMut:true;isSigner:false;name:"vaultAtaQuote"}, {isMut:false;isSigner:false;name:"tokenProgram"}, ]; args:[{name:"args";type:{defined:"SwapArgs"}}]; name:"swap"; }, { accounts:[{isMut:true;isSigner:false;name:"amm"}]; args:[]; name:"crankThatTwap"; }, ]; name:"amm"; types:[ { name:"AddLiquidityArgs"; type:{ fields:[ { docs:["How much quote token you will deposit to the pool"]; name:"quoteAmount"; type:"u64"; }, { docs:["The maximum base token you will deposit to the pool"]; name:"maxBaseAmount"; type:"u64"; }, { docs:["The minimum LP token you will get back"]; name:"minLpTokens"; type:"u64"; }, ]; kind:"struct"; }; }, { name:"CreateAmmArgs"; type:{ fields:[ {name:"twapInitialObservation";type:"u128"}, {name:"twapMaxObservationChangePerUpdate";type:"u128"}, ]; kind:"struct"; }; }, { name:"RemoveLiquidityArgs"; type:{ fields:[ {name:"lpTokensToBurn";type:"u64"}, {name:"minQuoteAmount";type:"u64"}, {name:"minBaseAmount";type:"u64"}, ]; kind:"struct"; }; }, { name:"SwapArgs"; type:{ fields:[ {name:"swapType";type:{defined:"SwapType"}}, {name:"inputAmount";type:"u64"}, {name:"outputAmountMin";type:"u64"}, ]; kind:"struct"; }; }, { name:"TwapOracle"; type:{ fields:[ {name:"lastUpdatedSlot";type:"u64"}, { docs:[ "A price is the number of quote units per base unit multiplied by 1e12.", "You cannot simply divide by 1e12 to get a price you can display in the UI", "because the base and quote decimals may be different. Instead, do:", "ui_price = (price * (10**(base_decimals - quote_decimals))) / 1e12", ]; name:"lastPrice"; type:"u128"; }, { docs:[ "If we did a raw TWAP over prices, someone could push the TWAP heavily with", "a few extremely large outliers. So we use observations, which can only move", "by `max_observation_change_per_update` per update.", ]; name:"lastObservation"; type:"u128"; }, { docs:[ "Running sum of slots_per_last_update * last_observation.", "", "Assuming latest observations are as big as possible (u64::MAX * 1e12),", "we can store 18 million slots worth of observations, which turns out to", "be ~85 days worth of slots.", "", "Assuming that latest observations are 100x smaller than they could theoretically", "be, we can store 8500 days (23 years) worth of them. Even this is a very", "very conservative assumption - META/USDC prices should be between 1e9 and", "1e15, which would overflow after 1e15 years worth of slots.", "", "So in the case of an overflow, the aggregator rolls back to 0. It's the", "client's responsibility to sanity check the assets or to handle an", "aggregator at t2 being smaller than an aggregator at t1.", ]; name:"aggregator"; type:"u128"; }, { docs:["The most that an observation can change per update."]; name:"maxObservationChangePerUpdate"; type:"u128"; }, { docs:["What the initial `latest_observation` is set to."]; name:"initialObservation"; type:"u128"; }, ]; kind:"struct"; }; }, { name:"SwapType"; type:{kind:"enum";variants:[{name:"Buy"},{name:"Sell"}]}; }, ]; version:"0.3.0"; }
errors:[ { code:6000; msg:"Can't get a TWAP before some observations have been stored"; name:"NoSlotsPassed"; }, { code:6001; msg:"Can't swap through a pool without token reserves on either side"; name:"NoReserves"; }, { code:6002; msg:"Input token amount is too large for a swap, causes overflow"; name:"InputAmountOverflow"; }, { code:6003; msg:"Add liquidity calculation error"; name:"AddLiquidityCalculationError"; }, { code:6004; msg:"Error in decimal scale conversion"; name:"DecimalScaleError"; }, { code:6005; msg:"You can't create an AMM pool where the token mints are the same"; name:"SameTokenMints"; }, { code:6006; msg:"A user wouldn't have gotten back their `output_amount_min`, reverting"; name:"SwapSlippageExceeded"; }, { code:6007; msg:"The user had insufficient balance to do this"; name:"InsufficientBalance"; }, { code:6008; msg:"Must remove a non-zero amount of liquidity"; name:"ZeroLiquidityRemove"; }, { code:6009; msg:"Cannot add liquidity with 0 tokens on either side"; name:"ZeroLiquidityToAdd"; }, { code:6010; msg:"Must specify a non-zero `min_lp_tokens` when adding to an existing pool"; name:"ZeroMinLpTokens"; }, { code:6011; msg:"LP wouldn't have gotten back `lp_token_min`"; name:"AddLiquiditySlippageExceeded"; }, { code:6012; msg:"LP would have spent more than `max_base_amount`"; name:"AddLiquidityMaxBaseExceeded"; }, { code:6013; msg:"`quote_amount` must be greater than 100000000 when initializing a pool"; name:"InsufficientQuoteAmount"; }, { code:6014; msg:"Users must swap a non-zero amount"; name:"ZeroSwapAmount"; }, { code:6015; msg:"K should always be increasing"; name:"ConstantProductInvariantFailed"; }, { code:6016; msg:"Casting has caused an overflow"; name:"CastingOverflow"; }, ]
types:[ { name:"AddLiquidityArgs"; type:{ fields:[ { docs:["How much quote token you will deposit to the pool"]; name:"quoteAmount"; type:"u64"; }, { docs:["The maximum base token you will deposit to the pool"]; name:"maxBaseAmount"; type:"u64"; }, { docs:["The minimum LP token you will get back"]; name:"minLpTokens"; type:"u64"; }, ]; kind:"struct"; }; }, { name:"CreateAmmArgs"; type:{ fields:[ {name:"twapInitialObservation";type:"u128"}, {name:"twapMaxObservationChangePerUpdate";type:"u128"}, ]; kind:"struct"; }; }, { name:"RemoveLiquidityArgs"; type:{ fields:[ {name:"lpTokensToBurn";type:"u64"}, {name:"minQuoteAmount";type:"u64"}, {name:"minBaseAmount";type:"u64"}, ]; kind:"struct"; }; }, { name:"SwapArgs"; type:{ fields:[ {name:"swapType";type:{defined:"SwapType"}}, {name:"inputAmount";type:"u64"}, {name:"outputAmountMin";type:"u64"}, ]; kind:"struct"; }; }, { name:"TwapOracle"; type:{ fields:[ {name:"lastUpdatedSlot";type:"u64"}, { docs:[ "A price is the number of quote units per base unit multiplied by 1e12.", "You cannot simply divide by 1e12 to get a price you can display in the UI", "because the base and quote decimals may be different. Instead, do:", "ui_price = (price * (10**(base_decimals - quote_decimals))) / 1e12", ]; name:"lastPrice"; type:"u128"; }, { docs:[ "If we did a raw TWAP over prices, someone could push the TWAP heavily with", "a few extremely large outliers. So we use observations, which can only move", "by `max_observation_change_per_update` per update.", ]; name:"lastObservation"; type:"u128"; }, { docs:[ "Running sum of slots_per_last_update * last_observation.", "", "Assuming latest observations are as big as possible (u64::MAX * 1e12),", "we can store 18 million slots worth of observations, which turns out to", "be ~85 days worth of slots.", "", "Assuming that latest observations are 100x smaller than they could theoretically", "be, we can store 8500 days (23 years) worth of them. Even this is a very", "very conservative assumption - META/USDC prices should be between 1e9 and", "1e15, which would overflow after 1e15 years worth of slots.", "", "So in the case of an overflow, the aggregator rolls back to 0. It's the", "client's responsibility to sanity check the assets or to handle an", "aggregator at t2 being smaller than an aggregator at t1.", ]; name:"aggregator"; type:"u128"; }, { docs:["The most that an observation can change per update."]; name:"maxObservationChangePerUpdate"; type:"u128"; }, { docs:["What the initial `latest_observation` is set to."]; name:"initialObservation"; type:"u128"; }, ]; kind:"struct"; }; }, { name:"SwapType"; type:{kind:"enum";variants:[{name:"Buy"},{name:"Sell"}]}; }, ]
typeAutocrat={ accounts:[ { name:"dao"; type:{ fields:[ {name:"treasuryPdaBump";type:"u8"}, {name:"treasury";type:"publicKey"}, {name:"tokenMint";type:"publicKey"}, {name:"usdcMint";type:"publicKey"}, {name:"proposalCount";type:"u32"}, {name:"passThresholdBps";type:"u16"}, {name:"slotsPerProposal";type:"u64"}, { docs:[ "For manipulation-resistance the TWAP is a time-weighted average observation,", "where observation tries to approximate price but can only move by", "`twap_max_observation_change_per_update` per update. Because it can only move", "a little bit per update, you need to check that it has a good initial observation.", "Otherwise, an attacker could create a very high initial observation in the pass", "market and a very low one in the fail market to force the proposal to pass.", "", "We recommend setting an initial observation around the spot price of the token,", "and max observation change per update around 2% the spot price of the token.", "For example, if the spot price of META is $400, we'd recommend setting an initial", "observation of 400 (converted into the AMM prices) and a max observation change per", "update of 8 (also converted into the AMM prices). Observations can be updated once", "a minute, so 2% allows the proposal market to reach double the spot price or 0", "in 50 minutes.", ]; name:"twapInitialObservation"; type:"u128"; }, {name:"twapMaxObservationChangePerUpdate";type:"u128"}, { docs:[ "As an anti-spam measure and to help liquidity, you need to lock up some liquidity", "in both futarchic markets in order to create a proposal.", "", "For example, for META, we can use a `min_quote_futarchic_liquidity` of", "5000 * 1_000_000 (5000 USDC) and a `min_base_futarchic_liquidity` of", "10 * 1_000_000_000 (10 META).", ]; name:"minQuoteFutarchicLiquidity"; type:"u64"; }, {name:"minBaseFutarchicLiquidity";type:"u64"}, ]; kind:"struct"; }; }, { name:"proposal"; type:{ fields:[ {name:"number";type:"u32"}, {name:"proposer";type:"publicKey"}, {name:"descriptionUrl";type:"string"}, {name:"slotEnqueued";type:"u64"}, {name:"state";type:{defined:"ProposalState"}}, {name:"instruction";type:{defined:"ProposalInstruction"}}, {name:"passAmm";type:"publicKey"}, {name:"failAmm";type:"publicKey"}, {name:"baseVault";type:"publicKey"}, {name:"quoteVault";type:"publicKey"}, {name:"dao";type:"publicKey"}, {name:"passLpTokensLocked";type:"u64"}, {name:"failLpTokensLocked";type:"u64"}, { docs:[ "We need to include a per-proposer nonce to prevent some weird proposal", "front-running edge cases. Using a `u64` means that proposers are unlikely", "to run into collisions, even if they generate nonces randomly - I've run", "the math :D", ]; name:"nonce"; type:"u64"; }, {name:"pdaBump";type:"u8"}, ]; kind:"struct"; }; }, ]; errors:[ { code:6000; msg:"Amms must have been created within 5 minutes (counted in slots) of proposal initialization"; name:"AmmTooOld"; }, { code:6001; msg:"An amm has an `initial_observation` that doesn't match the `dao`'s config"; name:"InvalidInitialObservation"; }, { code:6002; msg:"An amm has a `max_observation_change_per_update` that doesn't match the `dao`'s config"; name:"InvalidMaxObservationChange"; }, { code:6003; msg:"One of the vaults has an invalid `settlement_authority`"; name:"InvalidSettlementAuthority"; }, { code:6004; msg:"Proposal is too young to be executed or rejected"; name:"ProposalTooYoung"; }, { code:6005; msg:"Markets too young for proposal to be finalized. TWAP might need to be cranked"; name:"MarketsTooYoung"; }, { code:6006; msg:"This proposal has already been finalized"; name:"ProposalAlreadyFinalized"; }, { code:6007; msg:"A conditional vault has an invalid nonce. A nonce should encode the proposal number"; name:"InvalidVaultNonce"; }, { code:6008; msg:"This proposal can't be executed because it isn't in the passed state"; name:"ProposalNotPassed"; }, { code:6009; msg:"The proposer has fewer pass or fail LP tokens than they requested to lock"; name:"InsufficientLpTokenBalance"; }, { code:6010; msg:"The LP tokens passed in have less liquidity than the DAO's `min_quote_futarchic_liquidity` or `min_base_futachic_liquidity`"; name:"InsufficientLpTokenLock"; }, ]; instructions:[ { accounts:[ {isMut:true;isSigner:true;name:"dao"}, {isMut:true;isSigner:true;name:"payer"}, {isMut:false;isSigner:false;name:"systemProgram"}, {isMut:false;isSigner:false;name:"tokenMint"}, {isMut:false;isSigner:false;name:"usdcMint"}, ]; args:[{name:"params";type:{defined:"InitializeDaoParams"}}]; name:"initializeDao"; }, { accounts:[ {isMut:true;isSigner:false;name:"proposal"}, {isMut:true;isSigner:false;name:"dao"}, {isMut:false;isSigner:false;name:"quoteVault"}, {isMut:false;isSigner:false;name:"baseVault"}, {isMut:false;isSigner:false;name:"passAmm"}, {isMut:false;isSigner:false;name:"passLpMint"}, {isMut:false;isSigner:false;name:"failLpMint"}, {isMut:false;isSigner:false;name:"failAmm"}, {isMut:true;isSigner:false;name:"passLpUserAccount"}, {isMut:true;isSigner:false;name:"failLpUserAccount"}, {isMut:true;isSigner:false;name:"passLpVaultAccount"}, {isMut:true;isSigner:false;name:"failLpVaultAccount"}, {isMut:true;isSigner:true;name:"proposer"}, {isMut:false;isSigner:false;name:"tokenProgram"}, {isMut:false;isSigner:false;name:"systemProgram"}, ]; args:[{name:"params";type:{defined:"InitializeProposalParams"}}]; name:"initializeProposal"; }, { accounts:[ {isMut:true;isSigner:false;name:"proposal"}, {isMut:false;isSigner:false;name:"passAmm"}, {isMut:false;isSigner:false;name:"failAmm"}, {isMut:false;isSigner:false;name:"dao"}, {isMut:true;isSigner:false;name:"baseVault"}, {isMut:true;isSigner:false;name:"quoteVault"}, {isMut:false;isSigner:false;name:"treasury"}, {isMut:true;isSigner:false;name:"passLpUserAccount"}, {isMut:true;isSigner:false;name:"failLpUserAccount"}, {isMut:true;isSigner:false;name:"passLpVaultAccount"}, {isMut:true;isSigner:false;name:"failLpVaultAccount"}, {isMut:false;isSigner:false;name:"tokenProgram"}, {isMut:false;isSigner:false;name:"vaultProgram"}, ]; args:[]; name:"finalizeProposal"; }, { accounts:[ {isMut:true;isSigner:false;name:"proposal"}, {isMut:false;isSigner:false;name:"dao"}, ]; args:[]; name:"executeProposal"; }, { accounts:[ {isMut:true;isSigner:false;name:"dao"}, {isMut:false;isSigner:true;name:"treasury"}, ]; args:[{name:"daoParams";type:{defined:"UpdateDaoParams"}}]; name:"updateDao"; }, ]; name:"autocrat"; types:[ { name:"InitializeDaoParams"; type:{ fields:[ {name:"twapInitialObservation";type:"u128"}, {name:"twapMaxObservationChangePerUpdate";type:"u128"}, {name:"minQuoteFutarchicLiquidity";type:"u64"}, {name:"minBaseFutarchicLiquidity";type:"u64"}, {name:"passThresholdBps";type:{option:"u16"}}, {name:"slotsPerProposal";type:{option:"u64"}}, ]; kind:"struct"; }; }, { name:"InitializeProposalParams"; type:{ fields:[ {name:"descriptionUrl";type:"string"}, {name:"instruction";type:{defined:"ProposalInstruction"}}, {name:"passLpTokensToLock";type:"u64"}, {name:"failLpTokensToLock";type:"u64"}, {name:"nonce";type:"u64"}, ]; kind:"struct"; }; }, { name:"UpdateDaoParams"; type:{ fields:[ {name:"passThresholdBps";type:{option:"u16"}}, {name:"slotsPerProposal";type:{option:"u64"}}, {name:"twapInitialObservation";type:{option:"u128"}}, {name:"twapMaxObservationChangePerUpdate";type:{option:"u128"}}, {name:"minQuoteFutarchicLiquidity";type:{option:"u64"}}, {name:"minBaseFutarchicLiquidity";type:{option:"u64"}}, ]; kind:"struct"; }; }, { name:"ProposalAccount"; type:{ fields:[ {name:"pubkey";type:"publicKey"}, {name:"isSigner";type:"bool"}, {name:"isWritable";type:"bool"}, ]; kind:"struct"; }; }, { name:"ProposalInstruction"; type:{ fields:[ {name:"programId";type:"publicKey"}, {name:"accounts";type:{vec:{defined:"ProposalAccount"}}}, {name:"data";type:"bytes"}, ]; kind:"struct"; }; }, { name:"ProposalState"; type:{ kind:"enum"; variants:[ {name:"Pending"}, {name:"Passed"}, {name:"Failed"}, {name:"Executed"}, ]; }; }, ]; version:"0.3.0"; }
accounts:[ { name:"dao"; type:{ fields:[ {name:"treasuryPdaBump";type:"u8"}, {name:"treasury";type:"publicKey"}, {name:"tokenMint";type:"publicKey"}, {name:"usdcMint";type:"publicKey"}, {name:"proposalCount";type:"u32"}, {name:"passThresholdBps";type:"u16"}, {name:"slotsPerProposal";type:"u64"}, { docs:[ "For manipulation-resistance the TWAP is a time-weighted average observation,", "where observation tries to approximate price but can only move by", "`twap_max_observation_change_per_update` per update. Because it can only move", "a little bit per update, you need to check that it has a good initial observation.", "Otherwise, an attacker could create a very high initial observation in the pass", "market and a very low one in the fail market to force the proposal to pass.", "", "We recommend setting an initial observation around the spot price of the token,", "and max observation change per update around 2% the spot price of the token.", "For example, if the spot price of META is $400, we'd recommend setting an initial", "observation of 400 (converted into the AMM prices) and a max observation change per", "update of 8 (also converted into the AMM prices). Observations can be updated once", "a minute, so 2% allows the proposal market to reach double the spot price or 0", "in 50 minutes.", ]; name:"twapInitialObservation"; type:"u128"; }, {name:"twapMaxObservationChangePerUpdate";type:"u128"}, { docs:[ "As an anti-spam measure and to help liquidity, you need to lock up some liquidity", "in both futarchic markets in order to create a proposal.", "", "For example, for META, we can use a `min_quote_futarchic_liquidity` of", "5000 * 1_000_000 (5000 USDC) and a `min_base_futarchic_liquidity` of", "10 * 1_000_000_000 (10 META).", ]; name:"minQuoteFutarchicLiquidity"; type:"u64"; }, {name:"minBaseFutarchicLiquidity";type:"u64"}, ]; kind:"struct"; }; }, { name:"proposal"; type:{ fields:[ {name:"number";type:"u32"}, {name:"proposer";type:"publicKey"}, {name:"descriptionUrl";type:"string"}, {name:"slotEnqueued";type:"u64"}, {name:"state";type:{defined:"ProposalState"}}, {name:"instruction";type:{defined:"ProposalInstruction"}}, {name:"passAmm";type:"publicKey"}, {name:"failAmm";type:"publicKey"}, {name:"baseVault";type:"publicKey"}, {name:"quoteVault";type:"publicKey"}, {name:"dao";type:"publicKey"}, {name:"passLpTokensLocked";type:"u64"}, {name:"failLpTokensLocked";type:"u64"}, { docs:[ "We need to include a per-proposer nonce to prevent some weird proposal", "front-running edge cases. Using a `u64` means that proposers are unlikely", "to run into collisions, even if they generate nonces randomly - I've run", "the math :D", ]; name:"nonce"; type:"u64"; }, {name:"pdaBump";type:"u8"}, ]; kind:"struct"; }; }, ]
errors
errors:[ { code:6000; msg:"Amms must have been created within 5 minutes (counted in slots) of proposal initialization"; name:"AmmTooOld"; }, { code:6001; msg:"An amm has an `initial_observation` that doesn't match the `dao`'s config"; name:"InvalidInitialObservation"; }, { code:6002; msg:"An amm has a `max_observation_change_per_update` that doesn't match the `dao`'s config"; name:"InvalidMaxObservationChange"; }, { code:6003; msg:"One of the vaults has an invalid `settlement_authority`"; name:"InvalidSettlementAuthority"; }, { code:6004; msg:"Proposal is too young to be executed or rejected"; name:"ProposalTooYoung"; }, { code:6005; msg:"Markets too young for proposal to be finalized. TWAP might need to be cranked"; name:"MarketsTooYoung"; }, { code:6006; msg:"This proposal has already been finalized"; name:"ProposalAlreadyFinalized"; }, { code:6007; msg:"A conditional vault has an invalid nonce. A nonce should encode the proposal number"; name:"InvalidVaultNonce"; }, { code:6008; msg:"This proposal can't be executed because it isn't in the passed state"; name:"ProposalNotPassed"; }, { code:6009; msg:"The proposer has fewer pass or fail LP tokens than they requested to lock"; name:"InsufficientLpTokenBalance"; }, { code:6010; msg:"The LP tokens passed in have less liquidity than the DAO's `min_quote_futarchic_liquidity` or `min_base_futachic_liquidity`"; name:"InsufficientLpTokenLock"; }, ]
accounts:[ { name:"conditionalVault"; type:{ fields:[ {name:"status";type:{defined:"VaultStatus"}}, { docs:[ "The account that can either finalize the vault to make conditional tokens", "redeemable for underlying tokens or revert the vault to make deposit", "slips redeemable for underlying tokens.", ]; name:"settlementAuthority"; type:"publicKey"; }, { docs:["The mint of the tokens that are deposited into the vault."]; name:"underlyingTokenMint"; type:"publicKey"; }, { docs:["The vault's storage account for deposited funds."]; name:"underlyingTokenAccount"; type:"publicKey"; }, {name:"conditionalOnFinalizeTokenMint";type:"publicKey"}, {name:"conditionalOnRevertTokenMint";type:"publicKey"}, {name:"pdaBump";type:"u8"}, {name:"decimals";type:"u8"}, ]; kind:"struct"; }; }, ]
errors
errors:[ { code:6000; msg:"Insufficient underlying token balance to mint this amount of conditional tokens"; name:"InsufficientUnderlyingTokens"; }, { code:6001; msg:"This `vault_underlying_token_account` is not this vault's `underlying_token_account`"; name:"InvalidVaultUnderlyingTokenAccount"; }, { code:6002; msg:"This conditional token mint is not this vault's conditional token mint"; name:"InvalidConditionalTokenMint"; }, { code:6003; msg:"Vault needs to be settled as finalized before users can redeem conditional tokens for underlying tokens"; name:"CantRedeemConditionalTokens"; }, { code:6004; msg:"Once a vault has been settled, its status as either finalized or reverted cannot be changed"; name:"VaultAlreadySettled"; }, ]
typeAmmProgram={ accounts:[ { name:"amm"; type:{ fields:[ {name:"bump";type:"u8"}, {name:"createdAtSlot";type:"u64"}, {name:"lpMint";type:"publicKey"}, {name:"baseMint";type:"publicKey"}, {name:"quoteMint";type:"publicKey"}, {name:"baseMintDecimals";type:"u8"}, {name:"quoteMintDecimals";type:"u8"}, {name:"baseAmount";type:"u64"}, {name:"quoteAmount";type:"u64"}, {name:"oracle";type:{defined:"TwapOracle"}}, {name:"seqNum";type:"u64"}, ]; kind:"struct"; }; }, ]; errors:[ {code:6000;msg:"An assertion failed";name:"AssertFailed"}, { code:6001; msg:"Can't get a TWAP before some observations have been stored"; name:"NoSlotsPassed"; }, { code:6002; msg:"Can't swap through a pool without token reserves on either side"; name:"NoReserves"; }, { code:6003; msg:"Input token amount is too large for a swap, causes overflow"; name:"InputAmountOverflow"; }, { code:6004; msg:"Add liquidity calculation error"; name:"AddLiquidityCalculationError"; }, { code:6005; msg:"Error in decimal scale conversion"; name:"DecimalScaleError"; }, { code:6006; msg:"You can't create an AMM pool where the token mints are the same"; name:"SameTokenMints"; }, { code:6007; msg:"A user wouldn't have gotten back their `output_amount_min`, reverting"; name:"SwapSlippageExceeded"; }, { code:6008; msg:"The user had insufficient balance to do this"; name:"InsufficientBalance"; }, { code:6009; msg:"Must remove a non-zero amount of liquidity"; name:"ZeroLiquidityRemove"; }, { code:6010; msg:"Cannot add liquidity with 0 tokens on either side"; name:"ZeroLiquidityToAdd"; }, { code:6011; msg:"Must specify a non-zero `min_lp_tokens` when adding to an existing pool"; name:"ZeroMinLpTokens"; }, { code:6012; msg:"LP wouldn't have gotten back `lp_token_min`"; name:"AddLiquiditySlippageExceeded"; }, { code:6013; msg:"LP would have spent more than `max_base_amount`"; name:"AddLiquidityMaxBaseExceeded"; }, { code:6014; msg:"`quote_amount` must be greater than 100000000 when initializing a pool"; name:"InsufficientQuoteAmount"; }, { code:6015; msg:"Users must swap a non-zero amount"; name:"ZeroSwapAmount"; }, { code:6016; msg:"K should always be increasing"; name:"ConstantProductInvariantFailed"; }, { code:6017; msg:"Casting has caused an overflow"; name:"CastingOverflow"; }, ]; events:[ { fields:[ {index:false;name:"common";type:{defined:"CommonFields"}}, {index:false;name:"inputAmount";type:"u64"}, {index:false;name:"outputAmount";type:"u64"}, {index:false;name:"swapType";type:{defined:"SwapType"}}, ]; name:"SwapEvent"; }, { fields:[ {index:false;name:"common";type:{defined:"CommonFields"}}, {index:false;name:"quoteAmount";type:"u64"}, {index:false;name:"maxBaseAmount";type:"u64"}, {index:false;name:"minLpTokens";type:"u64"}, {index:false;name:"baseAmount";type:"u64"}, {index:false;name:"lpTokensMinted";type:"u64"}, ]; name:"AddLiquidityEvent"; }, { fields:[ {index:false;name:"common";type:{defined:"CommonFields"}}, {index:false;name:"lpTokensBurned";type:"u64"}, {index:false;name:"minQuoteAmount";type:"u64"}, {index:false;name:"minBaseAmount";type:"u64"}, {index:false;name:"baseAmount";type:"u64"}, {index:false;name:"quoteAmount";type:"u64"}, ]; name:"RemoveLiquidityEvent"; }, { fields:[ {index:false;name:"common";type:{defined:"CommonFields"}}, {index:false;name:"twapInitialObservation";type:"u128"}, { index:false; name:"twapMaxObservationChangePerUpdate"; type:"u128"; }, {index:false;name:"lpMint";type:"publicKey"}, {index:false;name:"baseMint";type:"publicKey"}, {index:false;name:"quoteMint";type:"publicKey"}, {index:false;name:"vaultAtaBase";type:"publicKey"}, {index:false;name:"vaultAtaQuote";type:"publicKey"}, ]; name:"CreateAmmEvent"; }, { fields:[ {index:false;name:"common";type:{defined:"CommonFields"}}, ]; name:"CrankThatTwapEvent"; }, ]; instructions:[ { accounts:[ {isMut:true;isSigner:true;name:"user"}, {isMut:true;isSigner:false;name:"amm"}, {isMut:true;isSigner:false;name:"lpMint"}, {isMut:false;isSigner:false;name:"baseMint"}, {isMut:false;isSigner:false;name:"quoteMint"}, {isMut:true;isSigner:false;name:"vaultAtaBase"}, {isMut:true;isSigner:false;name:"vaultAtaQuote"}, {isMut:false;isSigner:false;name:"associatedTokenProgram"}, {isMut:false;isSigner:false;name:"tokenProgram"}, {isMut:false;isSigner:false;name:"systemProgram"}, {isMut:false;isSigner:false;name:"eventAuthority"}, {isMut:false;isSigner:false;name:"program"}, ]; args:[{name:"args";type:{defined:"CreateAmmArgs"}}]; name:"createAmm"; }, { accounts:[ {isMut:true;isSigner:true;name:"user"}, {isMut:true;isSigner:false;name:"amm"}, {isMut:true;isSigner:false;name:"lpMint"}, {isMut:true;isSigner:false;name:"userLpAccount"}, {isMut:true;isSigner:false;name:"userBaseAccount"}, {isMut:true;isSigner:false;name:"userQuoteAccount"}, {isMut:true;isSigner:false;name:"vaultAtaBase"}, {isMut:true;isSigner:false;name:"vaultAtaQuote"}, {isMut:false;isSigner:false;name:"tokenProgram"}, {isMut:false;isSigner:false;name:"eventAuthority"}, {isMut:false;isSigner:false;name:"program"}, ]; args:[{name:"args";type:{defined:"AddLiquidityArgs"}}]; name:"addLiquidity"; }, { accounts:[ {isMut:true;isSigner:true;name:"user"}, {isMut:true;isSigner:false;name:"amm"}, {isMut:true;isSigner:false;name:"lpMint"}, {isMut:true;isSigner:false;name:"userLpAccount"}, {isMut:true;isSigner:false;name:"userBaseAccount"}, {isMut:true;isSigner:false;name:"userQuoteAccount"}, {isMut:true;isSigner:false;name:"vaultAtaBase"}, {isMut:true;isSigner:false;name:"vaultAtaQuote"}, {isMut:false;isSigner:false;name:"tokenProgram"}, {isMut:false;isSigner:false;name:"eventAuthority"}, {isMut:false;isSigner:false;name:"program"}, ]; args:[{name:"args";type:{defined:"RemoveLiquidityArgs"}}]; name:"removeLiquidity"; }, { accounts:[ {isMut:true;isSigner:true;name:"user"}, {isMut:true;isSigner:false;name:"amm"}, {isMut:true;isSigner:false;name:"userBaseAccount"}, {isMut:true;isSigner:false;name:"userQuoteAccount"}, {isMut:true;isSigner:false;name:"vaultAtaBase"}, {isMut:true;isSigner:false;name:"vaultAtaQuote"}, {isMut:false;isSigner:false;name:"tokenProgram"}, {isMut:false;isSigner:false;name:"eventAuthority"}, {isMut:false;isSigner:false;name:"program"}, ]; args:[{name:"args";type:{defined:"SwapArgs"}}]; name:"swap"; }, { accounts:[ {isMut:true;isSigner:false;name:"amm"}, {isMut:false;isSigner:false;name:"eventAuthority"}, {isMut:false;isSigner:false;name:"program"}, ]; args:[]; name:"crankThatTwap"; }, ]; name:"amm"; types:[ { name:"CommonFields"; type:{ fields:[ {name:"slot";type:"u64"}, {name:"unixTimestamp";type:"i64"}, {name:"user";type:"publicKey"}, {name:"amm";type:"publicKey"}, {name:"postBaseReserves";type:"u64"}, {name:"postQuoteReserves";type:"u64"}, {name:"oracleLastPrice";type:"u128"}, {name:"oracleLastObservation";type:"u128"}, {name:"oracleAggregator";type:"u128"}, {name:"seqNum";type:"u64"}, ]; kind:"struct"; }; }, { name:"AddLiquidityArgs"; type:{ fields:[ { docs:["How much quote token you will deposit to the pool"]; name:"quoteAmount"; type:"u64"; }, { docs:["The maximum base token you will deposit to the pool"]; name:"maxBaseAmount"; type:"u64"; }, { docs:["The minimum LP token you will get back"]; name:"minLpTokens"; type:"u64"; }, ]; kind:"struct"; }; }, { name:"CreateAmmArgs"; type:{ fields:[ {name:"twapInitialObservation";type:"u128"}, {name:"twapMaxObservationChangePerUpdate";type:"u128"}, {name:"twapStartDelaySlots";type:"u64"}, ]; kind:"struct"; }; }, { name:"RemoveLiquidityArgs"; type:{ fields:[ {name:"lpTokensToBurn";type:"u64"}, {name:"minQuoteAmount";type:"u64"}, {name:"minBaseAmount";type:"u64"}, ]; kind:"struct"; }; }, { name:"SwapArgs"; type:{ fields:[ {name:"swapType";type:{defined:"SwapType"}}, {name:"inputAmount";type:"u64"}, {name:"outputAmountMin";type:"u64"}, ]; kind:"struct"; }; }, { name:"TwapOracle"; type:{ fields:[ {name:"lastUpdatedSlot";type:"u64"}, { docs:[ "A price is the number of quote units per base unit multiplied by 1e12.", "You cannot simply divide by 1e12 to get a price you can display in the UI", "because the base and quote decimals may be different. Instead, do:", "ui_price = (price * (10**(base_decimals - quote_decimals))) / 1e12", ]; name:"lastPrice"; type:"u128"; }, { docs:[ "If we did a raw TWAP over prices, someone could push the TWAP heavily with", "a few extremely large outliers. So we use observations, which can only move", "by `max_observation_change_per_update` per update.", ]; name:"lastObservation"; type:"u128"; }, { docs:[ "Running sum of slots_per_last_update * last_observation.", "", "Assuming latest observations are as big as possible (u64::MAX * 1e12),", "we can store 18 million slots worth of observations, which turns out to", "be ~85 days worth of slots.", "", "Assuming that latest observations are 100x smaller than they could theoretically", "be, we can store 8500 days (23 years) worth of them. Even this is a very", "very conservative assumption - META/USDC prices should be between 1e9 and", "1e15, which would overflow after 1e15 years worth of slots.", "", "So in the case of an overflow, the aggregator rolls back to 0. It's the", "client's responsibility to sanity check the assets or to handle an", "aggregator at T2 being smaller than an aggregator at T1.", ]; name:"aggregator"; type:"u128"; }, { docs:["The most that an observation can change per update."]; name:"maxObservationChangePerUpdate"; type:"u128"; }, { docs:["What the initial `latest_observation` is set to."]; name:"initialObservation"; type:"u128"; }, { docs:[ "Number of slots after amm.created_at_slot to start recording TWAP", ]; name:"startDelaySlots"; type:"u64"; }, ]; kind:"struct"; }; }, { name:"SwapType"; type:{kind:"enum";variants:[{name:"Buy"},{name:"Sell"}]}; }, ]; version:"0.4.1"; }
errors:[ {code:6000;msg:"An assertion failed";name:"AssertFailed"}, { code:6001; msg:"Can't get a TWAP before some observations have been stored"; name:"NoSlotsPassed"; }, { code:6002; msg:"Can't swap through a pool without token reserves on either side"; name:"NoReserves"; }, { code:6003; msg:"Input token amount is too large for a swap, causes overflow"; name:"InputAmountOverflow"; }, { code:6004; msg:"Add liquidity calculation error"; name:"AddLiquidityCalculationError"; }, { code:6005; msg:"Error in decimal scale conversion"; name:"DecimalScaleError"; }, { code:6006; msg:"You can't create an AMM pool where the token mints are the same"; name:"SameTokenMints"; }, { code:6007; msg:"A user wouldn't have gotten back their `output_amount_min`, reverting"; name:"SwapSlippageExceeded"; }, { code:6008; msg:"The user had insufficient balance to do this"; name:"InsufficientBalance"; }, { code:6009; msg:"Must remove a non-zero amount of liquidity"; name:"ZeroLiquidityRemove"; }, { code:6010; msg:"Cannot add liquidity with 0 tokens on either side"; name:"ZeroLiquidityToAdd"; }, { code:6011; msg:"Must specify a non-zero `min_lp_tokens` when adding to an existing pool"; name:"ZeroMinLpTokens"; }, { code:6012; msg:"LP wouldn't have gotten back `lp_token_min`"; name:"AddLiquiditySlippageExceeded"; }, { code:6013; msg:"LP would have spent more than `max_base_amount`"; name:"AddLiquidityMaxBaseExceeded"; }, { code:6014; msg:"`quote_amount` must be greater than 100000000 when initializing a pool"; name:"InsufficientQuoteAmount"; }, { code:6015; msg:"Users must swap a non-zero amount"; name:"ZeroSwapAmount"; }, { code:6016; msg:"K should always be increasing"; name:"ConstantProductInvariantFailed"; }, { code:6017; msg:"Casting has caused an overflow"; name:"CastingOverflow"; }, ]
types:[ { name:"CommonFields"; type:{ fields:[ {name:"slot";type:"u64"}, {name:"unixTimestamp";type:"i64"}, {name:"user";type:"publicKey"}, {name:"amm";type:"publicKey"}, {name:"postBaseReserves";type:"u64"}, {name:"postQuoteReserves";type:"u64"}, {name:"oracleLastPrice";type:"u128"}, {name:"oracleLastObservation";type:"u128"}, {name:"oracleAggregator";type:"u128"}, {name:"seqNum";type:"u64"}, ]; kind:"struct"; }; }, { name:"AddLiquidityArgs"; type:{ fields:[ { docs:["How much quote token you will deposit to the pool"]; name:"quoteAmount"; type:"u64"; }, { docs:["The maximum base token you will deposit to the pool"]; name:"maxBaseAmount"; type:"u64"; }, { docs:["The minimum LP token you will get back"]; name:"minLpTokens"; type:"u64"; }, ]; kind:"struct"; }; }, { name:"CreateAmmArgs"; type:{ fields:[ {name:"twapInitialObservation";type:"u128"}, {name:"twapMaxObservationChangePerUpdate";type:"u128"}, {name:"twapStartDelaySlots";type:"u64"}, ]; kind:"struct"; }; }, { name:"RemoveLiquidityArgs"; type:{ fields:[ {name:"lpTokensToBurn";type:"u64"}, {name:"minQuoteAmount";type:"u64"}, {name:"minBaseAmount";type:"u64"}, ]; kind:"struct"; }; }, { name:"SwapArgs"; type:{ fields:[ {name:"swapType";type:{defined:"SwapType"}}, {name:"inputAmount";type:"u64"}, {name:"outputAmountMin";type:"u64"}, ]; kind:"struct"; }; }, { name:"TwapOracle"; type:{ fields:[ {name:"lastUpdatedSlot";type:"u64"}, { docs:[ "A price is the number of quote units per base unit multiplied by 1e12.", "You cannot simply divide by 1e12 to get a price you can display in the UI", "because the base and quote decimals may be different. Instead, do:", "ui_price = (price * (10**(base_decimals - quote_decimals))) / 1e12", ]; name:"lastPrice"; type:"u128"; }, { docs:[ "If we did a raw TWAP over prices, someone could push the TWAP heavily with", "a few extremely large outliers. So we use observations, which can only move", "by `max_observation_change_per_update` per update.", ]; name:"lastObservation"; type:"u128"; }, { docs:[ "Running sum of slots_per_last_update * last_observation.", "", "Assuming latest observations are as big as possible (u64::MAX * 1e12),", "we can store 18 million slots worth of observations, which turns out to", "be ~85 days worth of slots.", "", "Assuming that latest observations are 100x smaller than they could theoretically", "be, we can store 8500 days (23 years) worth of them. Even this is a very", "very conservative assumption - META/USDC prices should be between 1e9 and", "1e15, which would overflow after 1e15 years worth of slots.", "", "So in the case of an overflow, the aggregator rolls back to 0. It's the", "client's responsibility to sanity check the assets or to handle an", "aggregator at T2 being smaller than an aggregator at T1.", ]; name:"aggregator"; type:"u128"; }, { docs:["The most that an observation can change per update."]; name:"maxObservationChangePerUpdate"; type:"u128"; }, { docs:["What the initial `latest_observation` is set to."]; name:"initialObservation"; type:"u128"; }, { docs:[ "Number of slots after amm.created_at_slot to start recording TWAP", ]; name:"startDelaySlots"; type:"u64"; }, ]; kind:"struct"; }; }, { name:"SwapType"; type:{kind:"enum";variants:[{name:"Buy"},{name:"Sell"}]}; }, ]
typeAutocratProgram={ accounts:[ { name:"dao"; type:{ fields:[ {name:"treasuryPdaBump";type:"u8"}, {name:"treasury";type:"publicKey"}, {name:"tokenMint";type:"publicKey"}, {name:"usdcMint";type:"publicKey"}, {name:"proposalCount";type:"u32"}, {name:"passThresholdBps";type:"u16"}, {name:"slotsPerProposal";type:"u64"}, { docs:[ "For manipulation-resistance the TWAP is a time-weighted average observation,", "where observation tries to approximate price but can only move by", "`twap_max_observation_change_per_update` per update. Because it can only move", "a little bit per update, you need to check that it has a good initial observation.", "Otherwise, an attacker could create a very high initial observation in the pass", "market and a very low one in the fail market to force the proposal to pass.", "", "We recommend setting an initial observation around the spot price of the token,", "and max observation change per update around 2% the spot price of the token.", "For example, if the spot price of META is $400, we'd recommend setting an initial", "observation of 400 (converted into the AMM prices) and a max observation change per", "update of 8 (also converted into the AMM prices). Observations can be updated once", "a minute, so 2% allows the proposal market to reach double the spot price or 0", "in 50 minutes.", ]; name:"twapInitialObservation"; type:"u128"; }, {name:"twapMaxObservationChangePerUpdate";type:"u128"}, { docs:[ "Forces TWAP calculation to start after amm.created_at_slot + twap_start_delay_slots", ]; name:"twapStartDelaySlots"; type:"u64"; }, { docs:[ "As an anti-spam measure and to help liquidity, you need to lock up some liquidity", "in both futarchic markets in order to create a proposal.", "", "For example, for META, we can use a `min_quote_futarchic_liquidity` of", "5000 * 1_000_000 (5000 USDC) and a `min_base_futarchic_liquidity` of", "10 * 1_000_000_000 (10 META).", ]; name:"minQuoteFutarchicLiquidity"; type:"u64"; }, {name:"minBaseFutarchicLiquidity";type:"u64"}, {name:"seqNum";type:"u64"}, ]; kind:"struct"; }; }, { name:"proposal"; type:{ fields:[ {name:"number";type:"u32"}, {name:"proposer";type:"publicKey"}, {name:"descriptionUrl";type:"string"}, {name:"slotEnqueued";type:"u64"}, {name:"state";type:{defined:"ProposalState"}}, {name:"instruction";type:{defined:"ProposalInstruction"}}, {name:"passAmm";type:"publicKey"}, {name:"failAmm";type:"publicKey"}, {name:"baseVault";type:"publicKey"}, {name:"quoteVault";type:"publicKey"}, {name:"dao";type:"publicKey"}, {name:"passLpTokensLocked";type:"u64"}, {name:"failLpTokensLocked";type:"u64"}, { docs:[ "We need to include a per-proposer nonce to prevent some weird proposal", "front-running edge cases. Using a `u64` means that proposers are unlikely", "to run into collisions, even if they generate nonces randomly - I've run", "the math :D", ]; name:"nonce"; type:"u64"; }, {name:"pdaBump";type:"u8"}, {name:"question";type:"publicKey"}, {name:"durationInSlots";type:"u64"}, ]; kind:"struct"; }; }, ]; errors:[ { code:6000; msg:"Amms must have been created within 5 minutes (counted in slots) of proposal initialization"; name:"AmmTooOld"; }, { code:6001; msg:"An amm has an `initial_observation` that doesn't match the `dao`'s config"; name:"InvalidInitialObservation"; }, { code:6002; msg:"An amm has a `max_observation_change_per_update` that doesn't match the `dao`'s config"; name:"InvalidMaxObservationChange"; }, { code:6003; msg:"An amm has a `start_delay_slots` that doesn't match the `dao`'s config"; name:"InvalidStartDelaySlots"; }, { code:6004; msg:"One of the vaults has an invalid `settlement_authority`"; name:"InvalidSettlementAuthority"; }, { code:6005; msg:"Proposal is too young to be executed or rejected"; name:"ProposalTooYoung"; }, { code:6006; msg:"Markets too young for proposal to be finalized. TWAP might need to be cranked"; name:"MarketsTooYoung"; }, { code:6007; msg:"This proposal has already been finalized"; name:"ProposalAlreadyFinalized"; }, { code:6008; msg:"A conditional vault has an invalid nonce. A nonce should encode the proposal number"; name:"InvalidVaultNonce"; }, { code:6009; msg:"This proposal can't be executed because it isn't in the passed state"; name:"ProposalNotPassed"; }, { code:6010; msg:"The proposer has fewer pass or fail LP tokens than they requested to lock"; name:"InsufficientLpTokenBalance"; }, { code:6011; msg:"The LP tokens passed in have less liquidity than the DAO's `min_quote_futarchic_liquidity` or `min_base_futachic_liquidity`"; name:"InsufficientLpTokenLock"; }, ]; events:[ { fields:[ {index:false;name:"common";type:{defined:"CommonFields"}}, {index:false;name:"dao";type:"publicKey"}, {index:false;name:"tokenMint";type:"publicKey"}, {index:false;name:"usdcMint";type:"publicKey"}, {index:false;name:"treasury";type:"publicKey"}, {index:false;name:"passThresholdBps";type:"u16"}, {index:false;name:"slotsPerProposal";type:"u64"}, {index:false;name:"twapInitialObservation";type:"u128"}, { index:false; name:"twapMaxObservationChangePerUpdate"; type:"u128"; }, {index:false;name:"minQuoteFutarchicLiquidity";type:"u64"}, {index:false;name:"minBaseFutarchicLiquidity";type:"u64"}, ]; name:"InitializeDaoEvent"; }, { fields:[ {index:false;name:"common";type:{defined:"CommonFields"}}, {index:false;name:"dao";type:"publicKey"}, {index:false;name:"passThresholdBps";type:"u16"}, {index:false;name:"slotsPerProposal";type:"u64"}, {index:false;name:"twapInitialObservation";type:"u128"}, { index:false; name:"twapMaxObservationChangePerUpdate"; type:"u128"; }, {index:false;name:"minQuoteFutarchicLiquidity";type:"u64"}, {index:false;name:"minBaseFutarchicLiquidity";type:"u64"}, ]; name:"UpdateDaoEvent"; }, { fields:[ {index:false;name:"common";type:{defined:"CommonFields"}}, {index:false;name:"proposal";type:"publicKey"}, {index:false;name:"dao";type:"publicKey"}, {index:false;name:"question";type:"publicKey"}, {index:false;name:"quoteVault";type:"publicKey"}, {index:false;name:"baseVault";type:"publicKey"}, {index:false;name:"passAmm";type:"publicKey"}, {index:false;name:"failAmm";type:"publicKey"}, {index:false;name:"passLpMint";type:"publicKey"}, {index:false;name:"failLpMint";type:"publicKey"}, {index:false;name:"proposer";type:"publicKey"}, {index:false;name:"nonce";type:"u64"}, {index:false;name:"number";type:"u32"}, {index:false;name:"passLpTokensLocked";type:"u64"}, {index:false;name:"failLpTokensLocked";type:"u64"}, {index:false;name:"pdaBump";type:"u8"}, { index:false; name:"instruction"; type:{defined:"ProposalInstruction"}; }, {index:false;name:"durationInSlots";type:"u64"}, ]; name:"InitializeProposalEvent"; }, { fields:[ {index:false;name:"common";type:{defined:"CommonFields"}}, {index:false;name:"proposal";type:"publicKey"}, {index:false;name:"dao";type:"publicKey"}, {index:false;name:"passMarketTwap";type:"u128"}, {index:false;name:"failMarketTwap";type:"u128"}, {index:false;name:"threshold";type:"u128"}, {index:false;name:"state";type:{defined:"ProposalState"}}, ]; name:"FinalizeProposalEvent"; }, { fields:[ {index:false;name:"common";type:{defined:"CommonFields"}}, {index:false;name:"proposal";type:"publicKey"}, {index:false;name:"dao";type:"publicKey"}, ]; name:"ExecuteProposalEvent"; }, ]; instructions:[ { accounts:[ {isMut:true;isSigner:true;name:"dao"}, {isMut:true;isSigner:true;name:"payer"}, {isMut:false;isSigner:false;name:"systemProgram"}, {isMut:false;isSigner:false;name:"tokenMint"}, {isMut:false;isSigner:false;name:"usdcMint"}, {isMut:false;isSigner:false;name:"eventAuthority"}, {isMut:false;isSigner:false;name:"program"}, ]; args:[{name:"params";type:{defined:"InitializeDaoParams"}}]; name:"initializeDao"; }, { accounts:[ {isMut:true;isSigner:false;name:"proposal"}, {isMut:true;isSigner:false;name:"dao"}, {isMut:false;isSigner:false;name:"question"}, {isMut:false;isSigner:false;name:"quoteVault"}, {isMut:false;isSigner:false;name:"baseVault"}, {isMut:false;isSigner:false;name:"passAmm"}, {isMut:false;isSigner:false;name:"passLpMint"}, {isMut:false;isSigner:false;name:"failLpMint"}, {isMut:false;isSigner:false;name:"failAmm"}, {isMut:true;isSigner:false;name:"passLpUserAccount"}, {isMut:true;isSigner:false;name:"failLpUserAccount"}, {isMut:true;isSigner:false;name:"passLpVaultAccount"}, {isMut:true;isSigner:false;name:"failLpVaultAccount"}, {isMut:true;isSigner:true;name:"proposer"}, {isMut:false;isSigner:false;name:"tokenProgram"}, {isMut:false;isSigner:false;name:"systemProgram"}, {isMut:false;isSigner:false;name:"eventAuthority"}, {isMut:false;isSigner:false;name:"program"}, ]; args:[{name:"params";type:{defined:"InitializeProposalParams"}}]; name:"initializeProposal"; }, { accounts:[ {isMut:true;isSigner:false;name:"proposal"}, {isMut:false;isSigner:false;name:"passAmm"}, {isMut:false;isSigner:false;name:"failAmm"}, {isMut:false;isSigner:false;name:"dao"}, {isMut:true;isSigner:false;name:"question"}, {isMut:false;isSigner:false;name:"treasury"}, {isMut:true;isSigner:false;name:"passLpUserAccount"}, {isMut:true;isSigner:false;name:"failLpUserAccount"}, {isMut:true;isSigner:false;name:"passLpVaultAccount"}, {isMut:true;isSigner:false;name:"failLpVaultAccount"}, {isMut:false;isSigner:false;name:"tokenProgram"}, {isMut:false;isSigner:false;name:"vaultProgram"}, {isMut:false;isSigner:false;name:"vaultEventAuthority"}, {isMut:false;isSigner:false;name:"eventAuthority"}, {isMut:false;isSigner:false;name:"program"}, ]; args:[]; name:"finalizeProposal"; }, { accounts:[ {isMut:true;isSigner:false;name:"proposal"}, {isMut:false;isSigner:false;name:"dao"}, {isMut:false;isSigner:false;name:"eventAuthority"}, {isMut:false;isSigner:false;name:"program"}, ]; args:[]; name:"executeProposal"; }, { accounts:[ {isMut:true;isSigner:false;name:"dao"}, {isMut:false;isSigner:true;name:"treasury"}, {isMut:false;isSigner:false;name:"eventAuthority"}, {isMut:false;isSigner:false;name:"program"}, ]; args:[{name:"daoParams";type:{defined:"UpdateDaoParams"}}]; name:"updateDao"; }, ]; name:"autocrat"; types:[ { name:"CommonFields"; type:{ fields:[ {name:"slot";type:"u64"}, {name:"unixTimestamp";type:"i64"}, ]; kind:"struct"; }; }, { name:"InitializeDaoParams"; type:{ fields:[ {name:"twapInitialObservation";type:"u128"}, {name:"twapMaxObservationChangePerUpdate";type:"u128"}, {name:"twapStartDelaySlots";type:"u64"}, {name:"minQuoteFutarchicLiquidity";type:"u64"}, {name:"minBaseFutarchicLiquidity";type:"u64"}, {name:"passThresholdBps";type:{option:"u16"}}, {name:"slotsPerProposal";type:{option:"u64"}}, ]; kind:"struct"; }; }, { name:"InitializeProposalParams"; type:{ fields:[ {name:"descriptionUrl";type:"string"}, {name:"instruction";type:{defined:"ProposalInstruction"}}, {name:"passLpTokensToLock";type:"u64"}, {name:"failLpTokensToLock";type:"u64"}, {name:"nonce";type:"u64"}, ]; kind:"struct"; }; }, { name:"UpdateDaoParams"; type:{ fields:[ {name:"passThresholdBps";type:{option:"u16"}}, {name:"slotsPerProposal";type:{option:"u64"}}, {name:"twapInitialObservation";type:{option:"u128"}}, {name:"twapMaxObservationChangePerUpdate";type:{option:"u128"}}, {name:"minQuoteFutarchicLiquidity";type:{option:"u64"}}, {name:"minBaseFutarchicLiquidity";type:{option:"u64"}}, ]; kind:"struct"; }; }, { name:"ProposalAccount"; type:{ fields:[ {name:"pubkey";type:"publicKey"}, {name:"isSigner";type:"bool"}, {name:"isWritable";type:"bool"}, ]; kind:"struct"; }; }, { name:"ProposalInstruction"; type:{ fields:[ {name:"programId";type:"publicKey"}, {name:"accounts";type:{vec:{defined:"ProposalAccount"}}}, {name:"data";type:"bytes"}, ]; kind:"struct"; }; }, { name:"ProposalState"; type:{ kind:"enum"; variants:[ {name:"Pending"}, {name:"Passed"}, {name:"Failed"}, {name:"Executed"}, ]; }; }, ]; version:"0.4.2"; }
accounts:[ { name:"dao"; type:{ fields:[ {name:"treasuryPdaBump";type:"u8"}, {name:"treasury";type:"publicKey"}, {name:"tokenMint";type:"publicKey"}, {name:"usdcMint";type:"publicKey"}, {name:"proposalCount";type:"u32"}, {name:"passThresholdBps";type:"u16"}, {name:"slotsPerProposal";type:"u64"}, { docs:[ "For manipulation-resistance the TWAP is a time-weighted average observation,", "where observation tries to approximate price but can only move by", "`twap_max_observation_change_per_update` per update. Because it can only move", "a little bit per update, you need to check that it has a good initial observation.", "Otherwise, an attacker could create a very high initial observation in the pass", "market and a very low one in the fail market to force the proposal to pass.", "", "We recommend setting an initial observation around the spot price of the token,", "and max observation change per update around 2% the spot price of the token.", "For example, if the spot price of META is $400, we'd recommend setting an initial", "observation of 400 (converted into the AMM prices) and a max observation change per", "update of 8 (also converted into the AMM prices). Observations can be updated once", "a minute, so 2% allows the proposal market to reach double the spot price or 0", "in 50 minutes.", ]; name:"twapInitialObservation"; type:"u128"; }, {name:"twapMaxObservationChangePerUpdate";type:"u128"}, { docs:[ "Forces TWAP calculation to start after amm.created_at_slot + twap_start_delay_slots", ]; name:"twapStartDelaySlots"; type:"u64"; }, { docs:[ "As an anti-spam measure and to help liquidity, you need to lock up some liquidity", "in both futarchic markets in order to create a proposal.", "", "For example, for META, we can use a `min_quote_futarchic_liquidity` of", "5000 * 1_000_000 (5000 USDC) and a `min_base_futarchic_liquidity` of", "10 * 1_000_000_000 (10 META).", ]; name:"minQuoteFutarchicLiquidity"; type:"u64"; }, {name:"minBaseFutarchicLiquidity";type:"u64"}, {name:"seqNum";type:"u64"}, ]; kind:"struct"; }; }, { name:"proposal"; type:{ fields:[ {name:"number";type:"u32"}, {name:"proposer";type:"publicKey"}, {name:"descriptionUrl";type:"string"}, {name:"slotEnqueued";type:"u64"}, {name:"state";type:{defined:"ProposalState"}}, {name:"instruction";type:{defined:"ProposalInstruction"}}, {name:"passAmm";type:"publicKey"}, {name:"failAmm";type:"publicKey"}, {name:"baseVault";type:"publicKey"}, {name:"quoteVault";type:"publicKey"}, {name:"dao";type:"publicKey"}, {name:"passLpTokensLocked";type:"u64"}, {name:"failLpTokensLocked";type:"u64"}, { docs:[ "We need to include a per-proposer nonce to prevent some weird proposal", "front-running edge cases. Using a `u64` means that proposers are unlikely", "to run into collisions, even if they generate nonces randomly - I've run", "the math :D", ]; name:"nonce"; type:"u64"; }, {name:"pdaBump";type:"u8"}, {name:"question";type:"publicKey"}, {name:"durationInSlots";type:"u64"}, ]; kind:"struct"; }; }, ]
errors
errors:[ { code:6000; msg:"Amms must have been created within 5 minutes (counted in slots) of proposal initialization"; name:"AmmTooOld"; }, { code:6001; msg:"An amm has an `initial_observation` that doesn't match the `dao`'s config"; name:"InvalidInitialObservation"; }, { code:6002; msg:"An amm has a `max_observation_change_per_update` that doesn't match the `dao`'s config"; name:"InvalidMaxObservationChange"; }, { code:6003; msg:"An amm has a `start_delay_slots` that doesn't match the `dao`'s config"; name:"InvalidStartDelaySlots"; }, { code:6004; msg:"One of the vaults has an invalid `settlement_authority`"; name:"InvalidSettlementAuthority"; }, { code:6005; msg:"Proposal is too young to be executed or rejected"; name:"ProposalTooYoung"; }, { code:6006; msg:"Markets too young for proposal to be finalized. TWAP might need to be cranked"; name:"MarketsTooYoung"; }, { code:6007; msg:"This proposal has already been finalized"; name:"ProposalAlreadyFinalized"; }, { code:6008; msg:"A conditional vault has an invalid nonce. A nonce should encode the proposal number"; name:"InvalidVaultNonce"; }, { code:6009; msg:"This proposal can't be executed because it isn't in the passed state"; name:"ProposalNotPassed"; }, { code:6010; msg:"The proposer has fewer pass or fail LP tokens than they requested to lock"; name:"InsufficientLpTokenBalance"; }, { code:6011; msg:"The LP tokens passed in have less liquidity than the DAO's `min_quote_futarchic_liquidity` or `min_base_futachic_liquidity`"; name:"InsufficientLpTokenLock"; }, ]
accounts:[ { name:"conditionalVault"; type:{ fields:[ {name:"question";type:"publicKey"}, {name:"underlyingTokenMint";type:"publicKey"}, {name:"underlyingTokenAccount";type:"publicKey"}, {name:"conditionalTokenMints";type:{vec:"publicKey"}}, {name:"pdaBump";type:"u8"}, {name:"decimals";type:"u8"}, {name:"seqNum";type:"u64"}, ]; kind:"struct"; }; }, { docs:[ "Questions represent statements about future events.", "", "These statements include:", "- \"Will this proposal pass?\"", "- \"Who, if anyone, will be hired?\"", "- \"How effective will the grant committee deem this grant?\"", "", "Questions have 2 or more possible outcomes. For a question like \"will this", "proposal pass,\" the outcomes are \"yes\" and \"no.\" For a question like \"who", "will be hired,\" the outcomes could be \"Alice,\" \"Bob,\" and \"neither.\"", "", "Outcomes resolve to a number between 0 and 1. Binary questions like \"will", "this proposal pass\" have outcomes that resolve to exactly 0 or 1. You can", "also have questions with scalar outcomes. For example, the question \"how", "effective will the grant committee deem this grant\" could have two outcomes:", "\"ineffective\" and \"effective.\" If the grant committee deems the grant 70%", "effective, the \"effective\" outcome would resolve to 0.7 and the \"ineffective\"", "outcome would resolve to 0.3.", "", "Once resolved, the sum of all outcome resolutions is exactly 1.", ]; name:"question"; type:{ fields:[ {name:"questionId";type:{array:["u8",32]}}, {name:"oracle";type:"publicKey"}, {name:"payoutNumerators";type:{vec:"u32"}}, {name:"payoutDenominator";type:"u32"}, ]; kind:"struct"; }; }, ]
errors
errors:[ {code:6000;msg:"An assertion failed";name:"AssertFailed"}, { code:6001; msg:"Insufficient underlying token balance to mint this amount of conditional tokens"; name:"InsufficientUnderlyingTokens"; }, { code:6002; msg:"Insufficient conditional token balance to merge this `amount`"; name:"InsufficientConditionalTokens"; }, { code:6003; msg:"This `vault_underlying_token_account` is not this vault's `underlying_token_account`"; name:"InvalidVaultUnderlyingTokenAccount"; }, { code:6004; msg:"This conditional token mint is not this vault's conditional token mint"; name:"InvalidConditionalTokenMint"; }, { code:6005; msg:"Question needs to be resolved before users can redeem conditional tokens for underlying tokens"; name:"CantRedeemConditionalTokens"; }, { code:6006; msg:"Questions need 2 or more conditions"; name:"InsufficientNumConditions"; }, { code:6007; msg:"Invalid number of payout numerators"; name:"InvalidNumPayoutNumerators"; }, { code:6008; msg:"Client needs to pass in the list of conditional mints for a vault followed by the user's token accounts for those tokens"; name:"InvalidConditionals"; }, { code:6009; msg:"Conditional mint not in vault"; name:"ConditionalMintMismatch"; }, { code:6010; msg:"Unable to deserialize a conditional token mint"; name:"BadConditionalMint"; }, { code:6011; msg:"Unable to deserialize a conditional token account"; name:"BadConditionalTokenAccount"; }, { code:6012; msg:"User conditional token account mint does not match conditional mint"; name:"ConditionalTokenMintMismatch"; }, {code:6013;msg:"Payouts must sum to 1 or more";name:"PayoutZero"}, { code:6014; msg:"Question already resolved"; name:"QuestionAlreadyResolved"; }, { code:6015; msg:"Conditional token metadata already set"; name:"ConditionalTokenMetadataAlreadySet"; }, ]
accounts:[ { name:"fundingRecord"; type:{ fields:[ {docs:["The PDA bump."];name:"pdaBump";type:"u8"}, {docs:["The funder."];name:"funder";type:"publicKey"}, {docs:["The launch."];name:"launch";type:"publicKey"}, { docs:["The amount of USDC that has been committed by the funder."]; name:"committedAmount"; type:"u64"; }, { docs:[ "The sequence number of this funding record. Useful for sorting events.", ]; name:"seqNum"; type:"u64"; }, ]; kind:"struct"; }; }, { name:"launch"; type:{ fields:[ {docs:["The PDA bump."];name:"pdaBump";type:"u8"}, { docs:[ "The minimum amount of USDC that must be raised, otherwise", "everyone can get their USDC back.", ]; name:"minimumRaiseAmount"; type:"u64"; }, { docs:["The account that can start the launch."]; name:"launchAuthority"; type:"publicKey"; }, { docs:[ "The launch signer address. Needed because Raydium pools need a SOL payer and this PDA can't hold SOL.", ]; name:"launchSigner"; type:"publicKey"; }, { docs:["The PDA bump for the launch signer."]; name:"launchSignerPdaBump"; type:"u8"; }, { docs:[ "The USDC vault that will hold the USDC raised until the launch is over.", ]; name:"launchUsdcVault"; type:"publicKey"; }, { docs:["The token vault, used to send tokens to Raydium."]; name:"launchTokenVault"; type:"publicKey"; }, { docs:[ "The token that will be minted to funders and that will control the DAO.", ]; name:"tokenMint"; type:"publicKey"; }, {docs:["The USDC mint."];name:"usdcMint";type:"publicKey"}, { docs:["The unix timestamp when the launch was started."]; name:"unixTimestampStarted"; type:"i64"; }, { docs:["The amount of USDC that has been committed by the users."]; name:"totalCommittedAmount"; type:"u64"; }, { docs:["The state of the launch."]; name:"state"; type:{defined:"LaunchState"}; }, { docs:[ "The sequence number of this launch. Useful for sorting events.", ]; name:"seqNum"; type:"u64"; }, { docs:["The number of seconds that the launch will be live for."]; name:"secondsForLaunch"; type:"u32"; }, { docs:["The DAO, if the launch is complete."]; name:"dao"; type:{option:"publicKey"}; }, { docs:[ "The DAO treasury that USDC / LP is sent to, if the launch is complete.", ]; name:"daoTreasury"; type:{option:"publicKey"}; }, ]; kind:"struct"; }; }, ]
errors
errors:[ {code:6000;msg:"Invalid amount";name:"InvalidAmount"}, {code:6001;msg:"Supply must be zero";name:"SupplyNonZero"}, { code:6002; msg:"Launch period must be between 1 hour and 2 weeks"; name:"InvalidSecondsForLaunch"; }, {code:6003;msg:"Insufficient funds";name:"InsufficientFunds"}, { code:6004; msg:"Token mint key must end in 'meta'"; name:"InvalidTokenKey"; }, {code:6005;msg:"Invalid launch state";name:"InvalidLaunchState"}, {code:6006;msg:"Launch period not over";name:"LaunchPeriodNotOver"}, { code:6007; msg:"Launch is complete, no more funding allowed"; name:"LaunchExpired"; }, { code:6008; msg:"Launch needs to be in refunding state to get a refund"; name:"LaunchNotRefunding"; }, { code:6009; msg:"Launch must be initialized to be started"; name:"LaunchNotInitialized"; }, { code:6010; msg:"Freeze authority can't be set on launchpad tokens"; name:"FreezeAuthoritySet"; }, ]
Calculates the optimal swap amount and mergeable tokens without using square roots.
+