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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .github/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,9 @@ runs:
shell: bash

- name: Build test programs
run: |
make build-test-earn-programs
run: make build-test-earn-programs
shell: bash
Comment on lines 66 to 68

Copilot AI Mar 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI still runs make build-test-earn-programs, but that Makefile target currently builds an earn variant with --features migrate,testing. Since this PR removes the migrate feature from programs/earn/Cargo.toml, this step will fail unless the Makefile target (and any related tests expecting the migrate build) is updated accordingly.

Copilot uses AI. Check for mistakes.

- name: Build programs
run: |
anchor build -p earn
run: anchor build -p earn -- --features testing --no-default-features
shell: bash
5 changes: 1 addition & 4 deletions programs/earn/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,13 @@ name = "earn"

[features]
idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"]
default = ["testing"]
default = []
cpi = ["no-entrypoint"]
no-entrypoint = []
no-idl = []
no-log-ix-name = []
release = []
testing = []

Copilot AI Mar 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR removes the migrate, devnet, and mainnet features and also clears the default feature set. However, the repo still references these features in build tooling (e.g., Makefile builds --features migrate,testing and upgrade targets use --features devnet/mainnet), which will fail with "unknown feature" errors. Please update the build scripts/docs/CI to stop using the removed features (or keep the features until those references are removed).

Suggested change
testing = []
testing = []
migrate = []
devnet = []
mainnet = []

Copilot uses AI. Check for mistakes.
mainnet = []
devnet = []
migrate = []

[dependencies]
anchor-lang = { workspace = true, features = [
Expand Down
89 changes: 16 additions & 73 deletions programs/earn/src/instructions/admin/initialize.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,26 @@
// external dependencies
use anchor_lang::prelude::*;
use anchor_spl::{
associated_token::AssociatedToken,
token_2022::spl_token_2022::state::AccountState,
token_2022_extensions::spl_pod::optional_keys::OptionalNonZeroPubkey,
token_interface::{Mint, Token2022, TokenAccount},
};
use cfg_if::cfg_if;
use spl_token_2022::extension::{
default_account_state::DefaultAccountState, permanent_delegate::PermanentDelegate,
scaled_ui_amount::ScaledUiAmountConfig,
BaseStateWithExtensions,
ExtensionType,
scaled_ui_amount::ScaledUiAmountConfig, BaseStateWithExtensions, ExtensionType,
StateWithExtensions,
};

// local dependencies
use crate::{
constants::{ANCHOR_DISCRIMINATOR_SIZE, PORTAL_PROGRAM, INDEX_SCALE_F64},
constants::{ANCHOR_DISCRIMINATOR_SIZE, INDEX_SCALE_F64, PORTAL_PROGRAM},
errors::EarnError,
state::{EarnGlobal, GLOBAL_SEED, AUTHORITY_SEED},
utils::{conversion::{update_multiplier, index_to_multiplier}, token::thaw_token_account},
state::{EarnGlobal, AUTHORITY_SEED, GLOBAL_SEED},
utils::{
conversion::{index_to_multiplier, update_multiplier},
token::thaw_token_account,
},
};

cfg_if::cfg_if!(
if #[cfg(feature = "migrate")] {
declare_program!(old_earn);
use old_earn::{accounts::Global as OldGlobal, ID as OLD_EARN_PROGRAM_ID};
use crate::utils::conversion::{get_scaled_ui_config, principal_to_amount_up};
}
);

declare_program!(ext_swap);
use ext_swap::{constants::GLOBAL_SEED as SWAP_GLOBAL_SEED, ID as EXT_SWAP_PROGRAM_ID};

Expand All @@ -48,28 +38,13 @@ pub struct Initialize<'info> {
)]
pub global_account: Account<'info, EarnGlobal>,

#[cfg(feature = "migrate")]
#[account(
seeds = [GLOBAL_SEED],
seeds::program = OLD_EARN_PROGRAM_ID,
bump = old_global_account.bump,
)]
pub old_global_account: Account<'info, OldGlobal>,

#[account(
mut,
mint::token_program = token_program,
mint::decimals = 6, // Must be 6 decimals
)]
pub m_mint: InterfaceAccount<'info, Mint>,

#[cfg(feature = "migrate")]
#[account(
address = old_global_account.mint @ EarnError::InvalidMint,
mint::decimals = m_mint.decimals
)]
pub old_m_mint: InterfaceAccount<'info, Mint>,

/// CHECK: This account is validated by its seeds
#[account(
seeds = [AUTHORITY_SEED],
Expand Down Expand Up @@ -135,16 +110,9 @@ impl Initialize<'_> {
// Verify that the new multiplier is less than or equal to the current index (if migrating) or provided index (if not migrating)
// This is required because the call to our update_multiplier fn will fail silently if the multiplier on the mint is greater.
// That behavior is desired except when initializing the program. Therefore, we catch the error here.
let current_multiplier: f64;
let mint_multiplier: f64 = scaled_ui_config.new_multiplier.into();
cfg_if! {
if #[cfg(feature = "migrate")] {
current_multiplier = self.old_global_account.index as f64 / INDEX_SCALE_F64;
let current_multiplier = _current_index as f64 / INDEX_SCALE_F64;
Comment on lines 110 to +114

Copilot AI Mar 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment above the multiplier check still references migration logic ("if migrating" / "if not migrating"), but migration support has been removed from this instruction. Please update the comment to match the current behavior (it now always compares against the provided current_index).

Copilot uses AI. Check for mistakes.

} else {
current_multiplier = _current_index as f64 / INDEX_SCALE_F64;
}
}
if mint_multiplier > current_multiplier {
return err!(EarnError::InvalidMint);
}
Expand Down Expand Up @@ -196,39 +164,14 @@ impl Initialize<'_> {
bump: ctx.bumps.global_account,
});

cfg_if! {
if #[cfg(feature = "migrate")] {
// Set existing merkle root
ctx.accounts.global_account.earner_merkle_root = ctx.accounts.old_global_account.earner_merkle_root;

// Set the multiplier on the m_mint to the current index and timestamp on the old earn program
update_multiplier(
&mut ctx.accounts.m_mint, // mint
&ctx.accounts.global_account.to_account_info(), // authority
&[&[GLOBAL_SEED, &[ctx.bumps.global_account]]], // authority seeds
&ctx.accounts.token_program, // token program
index_to_multiplier(ctx.accounts.old_global_account.index)?, // index
ctx.accounts.old_global_account.timestamp as i64, // timestamp
)?;

// Check that the supply of the new mint (adjusted for the multiplier) is not greater than the supply of the old m mint
let scaled_ui_config = get_scaled_ui_config(&ctx.accounts.m_mint)?;
let new_supply_amount = principal_to_amount_up(ctx.accounts.m_mint.supply, scaled_ui_config.new_multiplier.into())?;

if new_supply_amount > ctx.accounts.old_m_mint.supply {
return err!(EarnError::InvalidMint);
}
} else {
update_multiplier(
&mut ctx.accounts.m_mint, // mint
&ctx.accounts.global_account.to_account_info(), // authority
&[&[GLOBAL_SEED, &[ctx.bumps.global_account]]], // authority seeds
&ctx.accounts.token_program, // token program
index_to_multiplier(_current_index)?, // index
Clock::get()?.unix_timestamp, // timestamp
)?;
}
}
update_multiplier(
&mut ctx.accounts.m_mint, // mint
&ctx.accounts.global_account.to_account_info(), // authority
&[&[GLOBAL_SEED, &[ctx.bumps.global_account]]], // authority seeds
&ctx.accounts.token_program, // token program
index_to_multiplier(_current_index)?, // index
Clock::get()?.unix_timestamp, // timestamp
)?;

// Thaw the portal and ext swap token accounts so they can be used (if not already thawed)
if ctx.accounts.portal_m_account.state == AccountState::Frozen {
Expand Down
6 changes: 0 additions & 6 deletions programs/earn/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,6 @@ pub mod earn {

// Admin instructions

#[cfg(feature = "migrate")]
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
Initialize::handler(ctx, 0)
}

#[cfg(not(feature = "migrate"))]
pub fn initialize(ctx: Context<Initialize>, current_index: u64) -> Result<()> {

Copilot AI Mar 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initialize now always requires a current_index argument. There are existing TS callers in the repo (e.g. tests/unit/earn.test.ts) that still call .initialize() with no args, which will break builds/tests once the IDL updates. Either update/remove those callers (and any migration-only flows), or reintroduce a backward-compatible instruction interface (e.g., accept Option<u64> and handle None).

Suggested change
pub fn initialize(ctx: Context<Initialize>, current_index: u64) -> Result<()> {
pub fn initialize(ctx: Context<Initialize>, current_index: Option<u64>) -> Result<()> {
let current_index = current_index.unwrap_or(0);

Copilot uses AI. Check for mistakes.
Initialize::handler(ctx, current_index)
}
Expand Down
2 changes: 1 addition & 1 deletion services/cli/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ async function main() {
.action(async ({ owner }) => {
const [payer, mint] = keysFromEnv(['PAYER_KEYPAIR', 'M_MINT_KEYPAIR']);

let mintAuth = PublicKey.findProgramAddressSync([Buffer.from('token_authority')], PROGRAMS.portal)[0];
let mintAuth = PublicKey.findProgramAddressSync([Buffer.from('authority')], PROGRAMS.portal)[0];
if (owner) {
mintAuth = new PublicKey(owner);
}
Expand Down
Loading