From 62aa1e175cb5aa3bff2f4a3151747f5f1d512f77 Mon Sep 17 00:00:00 2001 From: Kyrylo Stepanov Date: Wed, 7 Aug 2024 14:22:36 +0300 Subject: [PATCH 1/6] add check for an interaction with DAO --- program-states/src/error.rs | 6 ++++ .../src/instructions/claim.rs | 31 ++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/program-states/src/error.rs b/program-states/src/error.rs index 89f408b6..70dc4192 100644 --- a/program-states/src/error.rs +++ b/program-states/src/error.rs @@ -107,4 +107,10 @@ pub enum MplStakingError { // 6034 / 0x1792 #[msg("Rewards: Invalid reward pool account")] InvalidRewardPool, + // 6035 / 0x1793 + #[msg("Rewards: To claim rewards user must interact with DAO. It's impossible to check with that number of remaining accounts")] + RemainingAccountsIsEmpty, + // 6036 / 0x1794 + #[msg("Rewards: Passed remaining accounts are invalid, interaction with dao was'nt found")] + NoDaoInteractionFound, } diff --git a/programs/voter-stake-registry/src/instructions/claim.rs b/programs/voter-stake-registry/src/instructions/claim.rs index fdd312fa..94ec3bbb 100644 --- a/programs/voter-stake-registry/src/instructions/claim.rs +++ b/programs/voter-stake-registry/src/instructions/claim.rs @@ -3,7 +3,12 @@ use anchor_lang::prelude::*; use anchor_spl::token::{Token, TokenAccount}; use mplx_staking_states::{error::MplStakingError, state::Registrar}; use solana_program::program::get_return_data; -use std::borrow::Borrow; +use spl_governance::state::{ + legacy::GovernanceV1, proposal::ProposalV2, realm::RealmV2, vote_record::VoteRecordV2, +}; +use std::{borrow::Borrow, slice::Iter, str::FromStr}; + +pub const DAO_PUBKEY: &str = "89wVNeyqqDaWKWtS4rbunYdsxxbe5V3VRx6g8GWNMTMt"; #[derive(Accounts)] pub struct Claim<'info> { @@ -54,6 +59,21 @@ pub fn claim( realm_governing_mint_pubkey: Pubkey, realm_pubkey: Pubkey, ) -> Result { + let mut remaining_accounts_iter = ctx.remaining_accounts.iter(); + + let (_, realm_addr) = deserialize::(&mut remaining_accounts_iter)?; + let (governance, governance_addr) = deserialize::(&mut remaining_accounts_iter)?; + let (proposal, _) = deserialize::(&mut remaining_accounts_iter)?; + let (vote_record, _) = deserialize::(&mut remaining_accounts_iter)?; + + require!( + realm_addr == Pubkey::from_str(DAO_PUBKEY).unwrap() + && governance.realm == realm_addr + && proposal.governance == governance_addr + && vote_record.governing_token_owner == *ctx.accounts.mining_owner.key, + MplStakingError::NoDaoInteractionFound + ); + let registrar = ctx.accounts.registrar.load()?; require!( @@ -98,3 +118,12 @@ pub fn claim( Err(MplStakingError::CpiReturnDataIsAbsent.into()) } } + +fn deserialize(iter: &mut Iter) -> Result<(T, Pubkey)> { + let item = iter + .next() + .ok_or(MplStakingError::RemainingAccountsIsEmpty)?; + let addr = *item.key; + let obj = T::deserialize(&mut &item.try_borrow_mut_data()?[..])?; + Ok((obj, addr)) +} From ea70b1ec40da98426cf13aa8ce7e6a81f7812ccc Mon Sep 17 00:00:00 2001 From: Kyrylo Stepanov Date: Wed, 7 Aug 2024 15:39:25 +0300 Subject: [PATCH 2/6] rephrase the error message --- program-states/src/error.rs | 2 +- programs/voter-stake-registry/src/instructions/claim.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/program-states/src/error.rs b/program-states/src/error.rs index 70dc4192..a666861d 100644 --- a/program-states/src/error.rs +++ b/program-states/src/error.rs @@ -109,7 +109,7 @@ pub enum MplStakingError { InvalidRewardPool, // 6035 / 0x1793 #[msg("Rewards: To claim rewards user must interact with DAO. It's impossible to check with that number of remaining accounts")] - RemainingAccountsIsEmpty, + RemainingAccountsIsNotLongEnough, // 6036 / 0x1794 #[msg("Rewards: Passed remaining accounts are invalid, interaction with dao was'nt found")] NoDaoInteractionFound, diff --git a/programs/voter-stake-registry/src/instructions/claim.rs b/programs/voter-stake-registry/src/instructions/claim.rs index 94ec3bbb..3755920d 100644 --- a/programs/voter-stake-registry/src/instructions/claim.rs +++ b/programs/voter-stake-registry/src/instructions/claim.rs @@ -122,7 +122,7 @@ pub fn claim( fn deserialize(iter: &mut Iter) -> Result<(T, Pubkey)> { let item = iter .next() - .ok_or(MplStakingError::RemainingAccountsIsEmpty)?; + .ok_or(MplStakingError::RemainingAccountsIsNotLongEnough)?; let addr = *item.key; let obj = T::deserialize(&mut &item.try_borrow_mut_data()?[..])?; Ok((obj, addr)) From b2898118dfe879df5bd7fbeb4365a6912dcf8c90 Mon Sep 17 00:00:00 2001 From: Kyrylo Stepanov Date: Wed, 7 Aug 2024 17:59:50 +0300 Subject: [PATCH 3/6] deserialize governanceV2 instead of the V1 --- programs/voter-stake-registry/src/instructions/claim.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/voter-stake-registry/src/instructions/claim.rs b/programs/voter-stake-registry/src/instructions/claim.rs index 3755920d..df4272cf 100644 --- a/programs/voter-stake-registry/src/instructions/claim.rs +++ b/programs/voter-stake-registry/src/instructions/claim.rs @@ -4,11 +4,11 @@ use anchor_spl::token::{Token, TokenAccount}; use mplx_staking_states::{error::MplStakingError, state::Registrar}; use solana_program::program::get_return_data; use spl_governance::state::{ - legacy::GovernanceV1, proposal::ProposalV2, realm::RealmV2, vote_record::VoteRecordV2, + governance::GovernanceV2, proposal::ProposalV2, realm::RealmV2, vote_record::VoteRecordV2, }; use std::{borrow::Borrow, slice::Iter, str::FromStr}; -pub const DAO_PUBKEY: &str = "89wVNeyqqDaWKWtS4rbunYdsxxbe5V3VRx6g8GWNMTMt"; +pub const DAO_PUBKEY: &str = "some_dao_pubkey"; #[derive(Accounts)] pub struct Claim<'info> { @@ -62,7 +62,7 @@ pub fn claim( let mut remaining_accounts_iter = ctx.remaining_accounts.iter(); let (_, realm_addr) = deserialize::(&mut remaining_accounts_iter)?; - let (governance, governance_addr) = deserialize::(&mut remaining_accounts_iter)?; + let (governance, governance_addr) = deserialize::(&mut remaining_accounts_iter)?; let (proposal, _) = deserialize::(&mut remaining_accounts_iter)?; let (vote_record, _) = deserialize::(&mut remaining_accounts_iter)?; From 96c750a1786d77564a69fb48808fca574ea27bba Mon Sep 17 00:00:00 2001 From: Kyrylo Stepanov Date: Thu, 8 Aug 2024 11:42:42 +0300 Subject: [PATCH 4/6] refactor account passing && reduce number of passed accounts --- program-states/src/error.rs | 3 -- .../src/instructions/claim.rs | 40 +++++++++---------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/program-states/src/error.rs b/program-states/src/error.rs index a666861d..8e56b879 100644 --- a/program-states/src/error.rs +++ b/program-states/src/error.rs @@ -108,9 +108,6 @@ pub enum MplStakingError { #[msg("Rewards: Invalid reward pool account")] InvalidRewardPool, // 6035 / 0x1793 - #[msg("Rewards: To claim rewards user must interact with DAO. It's impossible to check with that number of remaining accounts")] - RemainingAccountsIsNotLongEnough, - // 6036 / 0x1794 #[msg("Rewards: Passed remaining accounts are invalid, interaction with dao was'nt found")] NoDaoInteractionFound, } diff --git a/programs/voter-stake-registry/src/instructions/claim.rs b/programs/voter-stake-registry/src/instructions/claim.rs index df4272cf..5efacacf 100644 --- a/programs/voter-stake-registry/src/instructions/claim.rs +++ b/programs/voter-stake-registry/src/instructions/claim.rs @@ -4,9 +4,9 @@ use anchor_spl::token::{Token, TokenAccount}; use mplx_staking_states::{error::MplStakingError, state::Registrar}; use solana_program::program::get_return_data; use spl_governance::state::{ - governance::GovernanceV2, proposal::ProposalV2, realm::RealmV2, vote_record::VoteRecordV2, + governance::GovernanceV2, proposal::ProposalV2, vote_record::VoteRecordV2, }; -use std::{borrow::Borrow, slice::Iter, str::FromStr}; +use std::{borrow::Borrow, str::FromStr}; pub const DAO_PUBKEY: &str = "some_dao_pubkey"; @@ -39,6 +39,16 @@ pub struct Claim<'info> { /// therefore their PDA that should sign the CPI call pub registrar: AccountLoader<'info, Registrar>, + /// CHECK: Can be an arbitrary account. + /// Can't be Account<'_, T> because doesn't implement AnchorDeserialize + pub governance: UncheckedAccount<'info>, + /// CHECK: Can be an arbitrary account. + /// Can't be Account<'_, T> because doesn't implement AnchorDeserialize + pub proposal: UncheckedAccount<'info>, + /// CHECK: Can be an arbitrary account. + /// Can't be Account<'_, T> because doesn't implement AnchorDeserialize + pub vote_record: UncheckedAccount<'info>, + #[account(mut)] pub user_reward_token_account: Account<'info, TokenAccount>, @@ -59,17 +69,16 @@ pub fn claim( realm_governing_mint_pubkey: Pubkey, realm_pubkey: Pubkey, ) -> Result { - let mut remaining_accounts_iter = ctx.remaining_accounts.iter(); - - let (_, realm_addr) = deserialize::(&mut remaining_accounts_iter)?; - let (governance, governance_addr) = deserialize::(&mut remaining_accounts_iter)?; - let (proposal, _) = deserialize::(&mut remaining_accounts_iter)?; - let (vote_record, _) = deserialize::(&mut remaining_accounts_iter)?; + let governance = + GovernanceV2::deserialize(&mut &ctx.accounts.governance.data.borrow_mut()[..])?; + let proposal = ProposalV2::deserialize(&mut &ctx.accounts.proposal.data.borrow_mut()[..])?; + let vote_record = + VoteRecordV2::deserialize(&mut &ctx.accounts.vote_record.data.borrow_mut()[..])?; require!( - realm_addr == Pubkey::from_str(DAO_PUBKEY).unwrap() - && governance.realm == realm_addr - && proposal.governance == governance_addr + realm_pubkey == Pubkey::from_str(DAO_PUBKEY).unwrap() + && governance.realm == realm_pubkey + && proposal.governance == ctx.accounts.governance.key() && vote_record.governing_token_owner == *ctx.accounts.mining_owner.key, MplStakingError::NoDaoInteractionFound ); @@ -118,12 +127,3 @@ pub fn claim( Err(MplStakingError::CpiReturnDataIsAbsent.into()) } } - -fn deserialize(iter: &mut Iter) -> Result<(T, Pubkey)> { - let item = iter - .next() - .ok_or(MplStakingError::RemainingAccountsIsNotLongEnough)?; - let addr = *item.key; - let obj = T::deserialize(&mut &item.try_borrow_mut_data()?[..])?; - Ok((obj, addr)) -} From f0e1e95e9b8dd8d4f3d78e99b7a88886d15e1f8d Mon Sep 17 00:00:00 2001 From: Kyrylo Stepanov Date: Thu, 8 Aug 2024 12:35:47 +0300 Subject: [PATCH 5/6] update idl --- ...voter_stake_registry.ts => mpl_staking.ts} | 1368 +++++------------ 1 file changed, 419 insertions(+), 949 deletions(-) rename idl/{voter_stake_registry.ts => mpl_staking.ts} (72%) diff --git a/idl/voter_stake_registry.ts b/idl/mpl_staking.ts similarity index 72% rename from idl/voter_stake_registry.ts rename to idl/mpl_staking.ts index c1fee068..c5f65436 100644 --- a/idl/voter_stake_registry.ts +++ b/idl/mpl_staking.ts @@ -1,6 +1,6 @@ -export type VoterStakeRegistry = { - "version": "0.2.4", - "name": "voter_stake_registry", +export type MplStaking = { + "version": "0.1.0", + "name": "mpl_staking", "docs": [ "# Introduction", "", @@ -107,10 +107,9 @@ export type VoterStakeRegistry = { "isMut": true, "isSigner": false, "docs": [ - "Account that will be created via CPI to the rewards,", - "it's responsible for being a \"root\" for all entities", - "inside rewards contract", - "PDA([\"reward_pool\", deposit_authority[aka registrar in our case]], rewards_program)" + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." ] }, { @@ -252,8 +251,9 @@ export type VoterStakeRegistry = { "isMut": true, "isSigner": false, "docs": [ - "PDA([\"reward_pool\", deposit_authority , fill_authority],", - "reward_program)" + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." ] }, { @@ -305,6 +305,11 @@ export type VoterStakeRegistry = { "isMut": false, "isSigner": true }, + { + "name": "delegateVoter", + "isMut": false, + "isSigner": false + }, { "name": "payer", "isMut": true, @@ -347,10 +352,6 @@ export type VoterStakeRegistry = { "type": { "defined": "LockupPeriod" } - }, - { - "name": "delegate", - "type": "publicKey" } ] }, @@ -533,15 +534,38 @@ export type VoterStakeRegistry = { "isMut": false, "isSigner": true }, + { + "name": "delegate", + "isMut": false, + "isSigner": false + }, + { + "name": "delegateMining", + "isMut": true, + "isSigner": false, + "docs": [ + "The address of the mining account on the rewards progra,", + "derived from PDA([\"mining\", delegate wallet addr, reward_pool], rewards_program)" + ] + }, { "name": "rewardPool", "isMut": true, - "isSigner": false + "isSigner": false, + "docs": [ + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." + ] }, { "name": "depositMining", "isMut": true, - "isSigner": false + "isSigner": false, + "docs": [ + "PDA([\"mining\", mining owner , reward_pool],", + "reward_program)" + ] }, { "name": "rewardsProgram", @@ -588,7 +612,9 @@ export type VoterStakeRegistry = { "isMut": false, "isSigner": false, "docs": [ - "PDA([\"reward_pool\", deposit_authority[aka registrar in our case]], rewards_program)" + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." ] }, { @@ -652,13 +678,28 @@ export type VoterStakeRegistry = { "isMut": false, "isSigner": true }, + { + "name": "delegate", + "isMut": false, + "isSigner": false + }, + { + "name": "delegateMining", + "isMut": true, + "isSigner": false, + "docs": [ + "The address of the mining account on the rewards progra,", + "derived from PDA([\"mining\", delegate wallet addr, reward_pool], rewards_program)" + ] + }, { "name": "rewardPool", "isMut": true, "isSigner": false, "docs": [ - "PDA([\"reward_pool\", deposit_authority , fill_authority],", - "reward_program)" + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." ] }, { @@ -709,13 +750,28 @@ export type VoterStakeRegistry = { "isMut": false, "isSigner": true }, + { + "name": "delegate", + "isMut": false, + "isSigner": false + }, + { + "name": "delegateMining", + "isMut": true, + "isSigner": false, + "docs": [ + "The address of the mining account on the rewards progra,", + "derived from PDA([\"mining\", delegate wallet addr, reward_pool], rewards_program)" + ] + }, { "name": "rewardPool", "isMut": true, "isSigner": false, "docs": [ - "PDA([\"reward_pool\", deposit_authority , fill_authority],", - "reward_program)" + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." ] }, { @@ -762,7 +818,9 @@ export type VoterStakeRegistry = { "isMut": false, "isSigner": false, "docs": [ - "PDA([\"reward_pool\", deposit_authority[aka registrar in our case]], rewards_program)" + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." ] }, { @@ -801,6 +859,30 @@ export type VoterStakeRegistry = { "therefore their PDA that should sign the CPI call" ] }, + { + "name": "governance", + "isMut": false, + "isSigner": false, + "docs": [ + "Can't be Account<'_, T> because doesn't implement AnchorDeserialize" + ] + }, + { + "name": "proposal", + "isMut": false, + "isSigner": false, + "docs": [ + "Can't be Account<'_, T> because doesn't implement AnchorDeserialize" + ] + }, + { + "name": "voteRecord", + "isMut": false, + "isSigner": false, + "docs": [ + "Can't be Account<'_, T> because doesn't implement AnchorDeserialize" + ] + }, { "name": "userRewardTokenAccount", "isMut": true, @@ -832,110 +914,81 @@ export type VoterStakeRegistry = { } ], "returns": "u64" - } - ], - "accounts": [ - { - "name": "registrar", - "docs": [ - "Instance of a voting rights distributor." - ], - "type": { - "kind": "struct", - "fields": [ - { - "name": "governanceProgramId", - "type": "publicKey" - }, - { - "name": "realm", - "type": "publicKey" - }, - { - "name": "realmGoverningTokenMint", - "type": "publicKey" - }, - { - "name": "realmAuthority", - "type": "publicKey" - }, - { - "name": "votingMints", - "docs": [ - "Storage for voting mints and their configuration.", - "The length should be adjusted for one's use case." - ], - "type": { - "array": [ - { - "defined": "VotingMintConfig" - }, - 2 - ] - } - }, - { - "name": "bump", - "type": "u8" - }, - { - "name": "padding", - "type": { - "array": [ - "u8", - 7 - ] - } - } - ] - } }, { - "name": "voter", - "docs": [ - "User account for minting voting rights." + "name": "changeDelegate", + "accounts": [ + { + "name": "registrar", + "isMut": false, + "isSigner": false + }, + { + "name": "voter", + "isMut": true, + "isSigner": false + }, + { + "name": "voterAuthority", + "isMut": false, + "isSigner": true + }, + { + "name": "delegateVoter", + "isMut": false, + "isSigner": false + }, + { + "name": "oldDelegateMining", + "isMut": true, + "isSigner": false, + "docs": [ + "The address of the mining account on the rewards program", + "derived from PDA([\"mining\", delegate wallet addr, reward_pool], rewards_program)", + "Seeds derivation will be checked on the rewards contract" + ] + }, + { + "name": "newDelegateMining", + "isMut": true, + "isSigner": false, + "docs": [ + "The address of the mining account on the rewards program", + "derived from PDA([\"mining\", delegate wallet addr, reward_pool], rewards_program)", + "Seeds derivation will be checked on the rewards contract" + ] + }, + { + "name": "rewardPool", + "isMut": true, + "isSigner": false, + "docs": [ + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." + ] + }, + { + "name": "depositMining", + "isMut": true, + "isSigner": false, + "docs": [ + "PDA([\"mining\", mining owner , reward_pool],", + "reward_program)" + ] + }, + { + "name": "rewardsProgram", + "isMut": false, + "isSigner": false + } ], - "type": { - "kind": "struct", - "fields": [ - { - "name": "deposits", - "type": { - "array": [ - { - "defined": "DepositEntry" - }, - 32 - ] - } - }, - { - "name": "voterAuthority", - "type": "publicKey" - }, - { - "name": "registrar", - "type": "publicKey" - }, - { - "name": "voterBump", - "type": "u8" - }, - { - "name": "voterWeightRecordBump", - "type": "u8" - }, - { - "name": "reserved1", - "type": { - "array": [ - "u8", - 14 - ] - } - } - ] - } + "args": [ + { + "name": "depositEntryIndex", + "type": "u8" + } + ] } ], "types": [ @@ -997,202 +1050,59 @@ export type VoterStakeRegistry = { } }, { - "name": "DepositEntry", - "docs": [ - "Bookkeeping for a single deposit for a given mint and lockup schedule." - ], + "name": "RewardsInstruction", "type": { - "kind": "struct", - "fields": [ - { - "name": "lockup", - "type": { - "defined": "Lockup" - } - }, - { - "name": "delegate", - "docs": [ - "Delegated staker" - ], - "type": "publicKey" - }, + "kind": "enum", + "variants": [ { - "name": "amountDepositedNative", - "docs": [ - "Amount in deposited, in native currency. Withdraws of vested tokens", - "directly reduce this amount.", - "", - "This directly tracks the total amount added by the user. They may", - "never withdraw more than this amount." - ], - "type": "u64" + "name": "InitializePool", + "fields": [ + { + "name": "fill_authority", + "docs": [ + "Account can fill the reward vault" + ], + "type": "publicKey" + }, + { + "name": "distribution_authority", + "docs": [ + "Account can distribute rewards for stakers" + ], + "type": "publicKey" + } + ] }, { - "name": "votingMintConfigIdx", - "type": "u8" + "name": "FillVault", + "fields": [ + { + "name": "amount", + "docs": [ + "Amount to fill" + ], + "type": "u64" + }, + { + "name": "distribution_ends_at", + "docs": [ + "Rewards distribution ends at given date" + ], + "type": "u64" + } + ] }, { - "name": "isUsed", - "type": "bool" - }, - { - "name": "reserved1", - "type": { - "array": [ - "u8", - 6 - ] - } - } - ] - } - }, - { - "name": "Lockup", - "type": { - "kind": "struct", - "fields": [ - { - "name": "startTs", - "docs": [ - "Start of the lockup." - ], - "type": "u64" - }, - { - "name": "endTs", - "docs": [ - "End of the lockup." - ], - "type": "u64" - }, - { - "name": "cooldownEndsAt", - "docs": [ - "End of the cooldown." - ], - "type": "u64" - }, - { - "name": "cooldownRequested", - "type": "bool" - }, - { - "name": "kind", - "docs": [ - "Type of lockup." - ], - "type": { - "defined": "LockupKind" - } - }, - { - "name": "period", - "docs": [ - "Type of lockup" - ], - "type": { - "defined": "LockupPeriod" - } - }, - { - "name": "reserved1", - "docs": [ - "Padding after period to align the struct size to 8 bytes" - ], - "type": { - "array": [ - "u8", - 5 - ] - } - } - ] - } - }, - { - "name": "VotingMintConfig", - "docs": [ - "Exchange rate for an asset that can be used to mint voting rights.", - "", - "See documentation of configure_voting_mint for details on how", - "native token amounts convert to vote weight." - ], - "type": { - "kind": "struct", - "fields": [ - { - "name": "mint", - "docs": [ - "Mint for this entry." - ], - "type": "publicKey" - }, - { - "name": "grantAuthority", - "docs": [ - "The authority that is allowed to push grants into voters" - ], - "type": "publicKey" - } - ] - } - }, - { - "name": "RewardsInstruction", - "type": { - "kind": "enum", - "variants": [ - { - "name": "InitializePool", - "fields": [ - { - "name": "fill_authority", - "docs": [ - "Account can fill the reward vault" - ], - "type": "publicKey" - }, - { - "name": "distribution_authority", - "docs": [ - "Account can distribute rewards for stakers" - ], - "type": "publicKey" - } - ] - }, - { - "name": "FillVault", - "fields": [ - { - "name": "amount", - "docs": [ - "Amount to fill" - ], - "type": "u64" - }, - { - "name": "distribution_ends_at", - "docs": [ - "Rewards distribution ends at given date" - ], - "type": "u64" - } - ] - }, - { - "name": "InitializeMining", - "fields": [ - { - "name": "mining_owner", - "docs": [ - "Represent the end-user, owner of the mining" - ], - "type": "publicKey" - } - ] + "name": "InitializeMining", + "fields": [ + { + "name": "mining_owner", + "docs": [ + "Represent the end-user, owner of the mining" + ], + "type": "publicKey" + } + ] }, { "name": "DepositMining", @@ -1304,46 +1214,18 @@ export type VoterStakeRegistry = { }, { "name": "CloseMining" - } - ] - } - }, - { - "name": "LockupPeriod", - "type": { - "kind": "enum", - "variants": [ - { - "name": "None" - }, - { - "name": "Flex" - }, - { - "name": "ThreeMonths" - }, - { - "name": "SixMonths" - }, - { - "name": "OneYear" - }, - { - "name": "Test" - } - ] - } - }, - { - "name": "LockupKind", - "type": { - "kind": "enum", - "variants": [ - { - "name": "None" }, { - "name": "Constant" + "name": "ChangeDelegate", + "fields": [ + { + "name": "staked_amount", + "docs": [ + "Amount of staked tokens" + ], + "type": "u64" + } + ] } ] } @@ -1404,159 +1286,12 @@ export type VoterStakeRegistry = { } ] } - ], - "errors": [ - { - "code": 6000, - "name": "VotingMintNotFound", - "msg": "" - }, - { - "code": 6001, - "name": "VotingTokenNonZero", - "msg": "" - }, - { - "code": 6002, - "name": "OutOfBoundsDepositEntryIndex", - "msg": "" - }, - { - "code": 6003, - "name": "UnusedDepositEntryIndex", - "msg": "" - }, - { - "code": 6004, - "name": "InsufficientUnlockedTokens", - "msg": "" - }, - { - "code": 6005, - "name": "InvalidLockupPeriod", - "msg": "" - }, - { - "code": 6006, - "name": "VotingMintConfigIndexAlreadyInUse", - "msg": "" - }, - { - "code": 6007, - "name": "OutOfBoundsVotingMintConfigIndex", - "msg": "" - }, - { - "code": 6008, - "name": "ForbiddenCpi", - "msg": "" - }, - { - "code": 6009, - "name": "InvalidMint", - "msg": "" - }, - { - "code": 6010, - "name": "DepositStillLocked", - "msg": "" - }, - { - "code": 6011, - "name": "InvalidAuthority", - "msg": "" - }, - { - "code": 6012, - "name": "InvalidTokenOwnerRecord", - "msg": "" - }, - { - "code": 6013, - "name": "InvalidRealmAuthority", - "msg": "" - }, - { - "code": 6014, - "name": "VoterWeightOverflow", - "msg": "" - }, - { - "code": 6015, - "name": "LockupSaturationMustBePositive", - "msg": "" - }, - { - "code": 6016, - "name": "VotingMintConfiguredWithDifferentIndex", - "msg": "" - }, - { - "code": 6017, - "name": "InternalProgramError", - "msg": "" - }, - { - "code": 6018, - "name": "InvalidLockupKind", - "msg": "" - }, - { - "code": 6019, - "name": "VaultTokenNonZero", - "msg": "" - }, - { - "code": 6020, - "name": "InvalidTimestampArguments", - "msg": "" - }, - { - "code": 6021, - "name": "UnlockMustBeCalledFirst", - "msg": "" - }, - { - "code": 6022, - "name": "UnlockAlreadyRequested", - "msg": "" - }, - { - "code": 6023, - "name": "ExtendDepositIsNotAllowed", - "msg": "" - }, - { - "code": 6024, - "name": "DepositingIsForbidded", - "msg": "To deposit additional tokens, extend the deposit" - }, - { - "code": 6025, - "name": "CpiReturnDataIsAbsent", - "msg": "Cpi call must return data, but data is absent" - }, - { - "code": 6026, - "name": "LockingIsForbidded", - "msg": "The source for the transfer only can be a deposit on DAO" - }, - { - "code": 6027, - "name": "DepositEntryIsOld", - "msg": "Locking up tokens is only allowed for freshly-deposited deposit entry" - }, - { - "code": 6028, - "name": "ArithmeticOverflow", - "msg": "Arithmetic operation has beed overflowed" - } ] }; -export const IDL: VoterStakeRegistry = { - "version": "0.2.4", - "name": "voter_stake_registry", +export const IDL: MplStaking = { + "version": "0.1.0", + "name": "mpl_staking", "docs": [ "# Introduction", "", @@ -1663,10 +1398,9 @@ export const IDL: VoterStakeRegistry = { "isMut": true, "isSigner": false, "docs": [ - "Account that will be created via CPI to the rewards,", - "it's responsible for being a \"root\" for all entities", - "inside rewards contract", - "PDA([\"reward_pool\", deposit_authority[aka registrar in our case]], rewards_program)" + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." ] }, { @@ -1808,8 +1542,9 @@ export const IDL: VoterStakeRegistry = { "isMut": true, "isSigner": false, "docs": [ - "PDA([\"reward_pool\", deposit_authority , fill_authority],", - "reward_program)" + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." ] }, { @@ -1861,6 +1596,11 @@ export const IDL: VoterStakeRegistry = { "isMut": false, "isSigner": true }, + { + "name": "delegateVoter", + "isMut": false, + "isSigner": false + }, { "name": "payer", "isMut": true, @@ -1903,10 +1643,6 @@ export const IDL: VoterStakeRegistry = { "type": { "defined": "LockupPeriod" } - }, - { - "name": "delegate", - "type": "publicKey" } ] }, @@ -2089,15 +1825,38 @@ export const IDL: VoterStakeRegistry = { "isMut": false, "isSigner": true }, + { + "name": "delegate", + "isMut": false, + "isSigner": false + }, + { + "name": "delegateMining", + "isMut": true, + "isSigner": false, + "docs": [ + "The address of the mining account on the rewards progra,", + "derived from PDA([\"mining\", delegate wallet addr, reward_pool], rewards_program)" + ] + }, { "name": "rewardPool", "isMut": true, - "isSigner": false + "isSigner": false, + "docs": [ + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." + ] }, { "name": "depositMining", "isMut": true, - "isSigner": false + "isSigner": false, + "docs": [ + "PDA([\"mining\", mining owner , reward_pool],", + "reward_program)" + ] }, { "name": "rewardsProgram", @@ -2144,7 +1903,9 @@ export const IDL: VoterStakeRegistry = { "isMut": false, "isSigner": false, "docs": [ - "PDA([\"reward_pool\", deposit_authority[aka registrar in our case]], rewards_program)" + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." ] }, { @@ -2208,13 +1969,28 @@ export const IDL: VoterStakeRegistry = { "isMut": false, "isSigner": true }, + { + "name": "delegate", + "isMut": false, + "isSigner": false + }, + { + "name": "delegateMining", + "isMut": true, + "isSigner": false, + "docs": [ + "The address of the mining account on the rewards progra,", + "derived from PDA([\"mining\", delegate wallet addr, reward_pool], rewards_program)" + ] + }, { "name": "rewardPool", "isMut": true, "isSigner": false, "docs": [ - "PDA([\"reward_pool\", deposit_authority , fill_authority],", - "reward_program)" + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." ] }, { @@ -2265,13 +2041,28 @@ export const IDL: VoterStakeRegistry = { "isMut": false, "isSigner": true }, + { + "name": "delegate", + "isMut": false, + "isSigner": false + }, + { + "name": "delegateMining", + "isMut": true, + "isSigner": false, + "docs": [ + "The address of the mining account on the rewards progra,", + "derived from PDA([\"mining\", delegate wallet addr, reward_pool], rewards_program)" + ] + }, { "name": "rewardPool", "isMut": true, "isSigner": false, "docs": [ - "PDA([\"reward_pool\", deposit_authority , fill_authority],", - "reward_program)" + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." ] }, { @@ -2318,7 +2109,9 @@ export const IDL: VoterStakeRegistry = { "isMut": false, "isSigner": false, "docs": [ - "PDA([\"reward_pool\", deposit_authority[aka registrar in our case]], rewards_program)" + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." ] }, { @@ -2358,8 +2151,32 @@ export const IDL: VoterStakeRegistry = { ] }, { - "name": "userRewardTokenAccount", - "isMut": true, + "name": "governance", + "isMut": false, + "isSigner": false, + "docs": [ + "Can't be Account<'_, T> because doesn't implement AnchorDeserialize" + ] + }, + { + "name": "proposal", + "isMut": false, + "isSigner": false, + "docs": [ + "Can't be Account<'_, T> because doesn't implement AnchorDeserialize" + ] + }, + { + "name": "voteRecord", + "isMut": false, + "isSigner": false, + "docs": [ + "Can't be Account<'_, T> because doesn't implement AnchorDeserialize" + ] + }, + { + "name": "userRewardTokenAccount", + "isMut": true, "isSigner": false }, { @@ -2388,110 +2205,81 @@ export const IDL: VoterStakeRegistry = { } ], "returns": "u64" - } - ], - "accounts": [ - { - "name": "registrar", - "docs": [ - "Instance of a voting rights distributor." - ], - "type": { - "kind": "struct", - "fields": [ - { - "name": "governanceProgramId", - "type": "publicKey" - }, - { - "name": "realm", - "type": "publicKey" - }, - { - "name": "realmGoverningTokenMint", - "type": "publicKey" - }, - { - "name": "realmAuthority", - "type": "publicKey" - }, - { - "name": "votingMints", - "docs": [ - "Storage for voting mints and their configuration.", - "The length should be adjusted for one's use case." - ], - "type": { - "array": [ - { - "defined": "VotingMintConfig" - }, - 2 - ] - } - }, - { - "name": "bump", - "type": "u8" - }, - { - "name": "padding", - "type": { - "array": [ - "u8", - 7 - ] - } - } - ] - } }, { - "name": "voter", - "docs": [ - "User account for minting voting rights." + "name": "changeDelegate", + "accounts": [ + { + "name": "registrar", + "isMut": false, + "isSigner": false + }, + { + "name": "voter", + "isMut": true, + "isSigner": false + }, + { + "name": "voterAuthority", + "isMut": false, + "isSigner": true + }, + { + "name": "delegateVoter", + "isMut": false, + "isSigner": false + }, + { + "name": "oldDelegateMining", + "isMut": true, + "isSigner": false, + "docs": [ + "The address of the mining account on the rewards program", + "derived from PDA([\"mining\", delegate wallet addr, reward_pool], rewards_program)", + "Seeds derivation will be checked on the rewards contract" + ] + }, + { + "name": "newDelegateMining", + "isMut": true, + "isSigner": false, + "docs": [ + "The address of the mining account on the rewards program", + "derived from PDA([\"mining\", delegate wallet addr, reward_pool], rewards_program)", + "Seeds derivation will be checked on the rewards contract" + ] + }, + { + "name": "rewardPool", + "isMut": true, + "isSigner": false, + "docs": [ + "Ownership of the account will be checked in the rewards contract", + "It's the core account for the rewards contract, which will", + "keep track of all rewards and staking logic." + ] + }, + { + "name": "depositMining", + "isMut": true, + "isSigner": false, + "docs": [ + "PDA([\"mining\", mining owner , reward_pool],", + "reward_program)" + ] + }, + { + "name": "rewardsProgram", + "isMut": false, + "isSigner": false + } ], - "type": { - "kind": "struct", - "fields": [ - { - "name": "deposits", - "type": { - "array": [ - { - "defined": "DepositEntry" - }, - 32 - ] - } - }, - { - "name": "voterAuthority", - "type": "publicKey" - }, - { - "name": "registrar", - "type": "publicKey" - }, - { - "name": "voterBump", - "type": "u8" - }, - { - "name": "voterWeightRecordBump", - "type": "u8" - }, - { - "name": "reserved1", - "type": { - "array": [ - "u8", - 14 - ] - } - } - ] - } + "args": [ + { + "name": "depositEntryIndex", + "type": "u8" + } + ] } ], "types": [ @@ -2552,149 +2340,6 @@ export const IDL: VoterStakeRegistry = { ] } }, - { - "name": "DepositEntry", - "docs": [ - "Bookkeeping for a single deposit for a given mint and lockup schedule." - ], - "type": { - "kind": "struct", - "fields": [ - { - "name": "lockup", - "type": { - "defined": "Lockup" - } - }, - { - "name": "delegate", - "docs": [ - "Delegated staker" - ], - "type": "publicKey" - }, - { - "name": "amountDepositedNative", - "docs": [ - "Amount in deposited, in native currency. Withdraws of vested tokens", - "directly reduce this amount.", - "", - "This directly tracks the total amount added by the user. They may", - "never withdraw more than this amount." - ], - "type": "u64" - }, - { - "name": "votingMintConfigIdx", - "type": "u8" - }, - { - "name": "isUsed", - "type": "bool" - }, - { - "name": "reserved1", - "type": { - "array": [ - "u8", - 6 - ] - } - } - ] - } - }, - { - "name": "Lockup", - "type": { - "kind": "struct", - "fields": [ - { - "name": "startTs", - "docs": [ - "Start of the lockup." - ], - "type": "u64" - }, - { - "name": "endTs", - "docs": [ - "End of the lockup." - ], - "type": "u64" - }, - { - "name": "cooldownEndsAt", - "docs": [ - "End of the cooldown." - ], - "type": "u64" - }, - { - "name": "cooldownRequested", - "type": "bool" - }, - { - "name": "kind", - "docs": [ - "Type of lockup." - ], - "type": { - "defined": "LockupKind" - } - }, - { - "name": "period", - "docs": [ - "Type of lockup" - ], - "type": { - "defined": "LockupPeriod" - } - }, - { - "name": "reserved1", - "docs": [ - "Padding after period to align the struct size to 8 bytes" - ], - "type": { - "array": [ - "u8", - 5 - ] - } - } - ] - } - }, - { - "name": "VotingMintConfig", - "docs": [ - "Exchange rate for an asset that can be used to mint voting rights.", - "", - "See documentation of configure_voting_mint for details on how", - "native token amounts convert to vote weight." - ], - "type": { - "kind": "struct", - "fields": [ - { - "name": "mint", - "docs": [ - "Mint for this entry." - ], - "type": "publicKey" - }, - { - "name": "grantAuthority", - "docs": [ - "The authority that is allowed to push grants into voters" - ], - "type": "publicKey" - } - ] - } - }, { "name": "RewardsInstruction", "type": { @@ -2860,46 +2505,18 @@ export const IDL: VoterStakeRegistry = { }, { "name": "CloseMining" - } - ] - } - }, - { - "name": "LockupPeriod", - "type": { - "kind": "enum", - "variants": [ - { - "name": "None" - }, - { - "name": "Flex" - }, - { - "name": "ThreeMonths" - }, - { - "name": "SixMonths" - }, - { - "name": "OneYear" }, { - "name": "Test" - } - ] - } - }, - { - "name": "LockupKind", - "type": { - "kind": "enum", - "variants": [ - { - "name": "None" - }, - { - "name": "Constant" + "name": "ChangeDelegate", + "fields": [ + { + "name": "staked_amount", + "docs": [ + "Amount of staked tokens" + ], + "type": "u64" + } + ] } ] } @@ -2960,152 +2577,5 @@ export const IDL: VoterStakeRegistry = { } ] } - ], - "errors": [ - { - "code": 6000, - "name": "VotingMintNotFound", - "msg": "" - }, - { - "code": 6001, - "name": "VotingTokenNonZero", - "msg": "" - }, - { - "code": 6002, - "name": "OutOfBoundsDepositEntryIndex", - "msg": "" - }, - { - "code": 6003, - "name": "UnusedDepositEntryIndex", - "msg": "" - }, - { - "code": 6004, - "name": "InsufficientUnlockedTokens", - "msg": "" - }, - { - "code": 6005, - "name": "InvalidLockupPeriod", - "msg": "" - }, - { - "code": 6006, - "name": "VotingMintConfigIndexAlreadyInUse", - "msg": "" - }, - { - "code": 6007, - "name": "OutOfBoundsVotingMintConfigIndex", - "msg": "" - }, - { - "code": 6008, - "name": "ForbiddenCpi", - "msg": "" - }, - { - "code": 6009, - "name": "InvalidMint", - "msg": "" - }, - { - "code": 6010, - "name": "DepositStillLocked", - "msg": "" - }, - { - "code": 6011, - "name": "InvalidAuthority", - "msg": "" - }, - { - "code": 6012, - "name": "InvalidTokenOwnerRecord", - "msg": "" - }, - { - "code": 6013, - "name": "InvalidRealmAuthority", - "msg": "" - }, - { - "code": 6014, - "name": "VoterWeightOverflow", - "msg": "" - }, - { - "code": 6015, - "name": "LockupSaturationMustBePositive", - "msg": "" - }, - { - "code": 6016, - "name": "VotingMintConfiguredWithDifferentIndex", - "msg": "" - }, - { - "code": 6017, - "name": "InternalProgramError", - "msg": "" - }, - { - "code": 6018, - "name": "InvalidLockupKind", - "msg": "" - }, - { - "code": 6019, - "name": "VaultTokenNonZero", - "msg": "" - }, - { - "code": 6020, - "name": "InvalidTimestampArguments", - "msg": "" - }, - { - "code": 6021, - "name": "UnlockMustBeCalledFirst", - "msg": "" - }, - { - "code": 6022, - "name": "UnlockAlreadyRequested", - "msg": "" - }, - { - "code": 6023, - "name": "ExtendDepositIsNotAllowed", - "msg": "" - }, - { - "code": 6024, - "name": "DepositingIsForbidded", - "msg": "To deposit additional tokens, extend the deposit" - }, - { - "code": 6025, - "name": "CpiReturnDataIsAbsent", - "msg": "Cpi call must return data, but data is absent" - }, - { - "code": 6026, - "name": "LockingIsForbidded", - "msg": "The source for the transfer only can be a deposit on DAO" - }, - { - "code": 6027, - "name": "DepositEntryIsOld", - "msg": "Locking up tokens is only allowed for freshly-deposited deposit entry" - }, - { - "code": 6028, - "name": "ArithmeticOverflow", - "msg": "Arithmetic operation has beed overflowed" - } ] }; From 4bb1f35da2be5e557713bcc77fef4b02e488ace6 Mon Sep 17 00:00:00 2001 From: Kyrylo Stepanov Date: Thu, 8 Aug 2024 17:21:26 +0300 Subject: [PATCH 6/6] add todo --- programs/voter-stake-registry/src/instructions/claim.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/programs/voter-stake-registry/src/instructions/claim.rs b/programs/voter-stake-registry/src/instructions/claim.rs index 5efacacf..44f4d92e 100644 --- a/programs/voter-stake-registry/src/instructions/claim.rs +++ b/programs/voter-stake-registry/src/instructions/claim.rs @@ -8,6 +8,7 @@ use spl_governance::state::{ }; use std::{borrow::Borrow, str::FromStr}; +// TODO: replace placeholder with the actual DAO pubkey pub const DAO_PUBKEY: &str = "some_dao_pubkey"; #[derive(Accounts)]