Skip to content

Commit 1907d26

Browse files
committed
fix: validate scaledui multiplier on initialize
1 parent 04269b2 commit 1907d26

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

programs/earn/src/instructions/admin/initialize.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use spl_token_2022::extension::{
1717

1818
// local dependencies
1919
use crate::{
20-
constants::{ANCHOR_DISCRIMINATOR_SIZE, PORTAL_PROGRAM},
20+
constants::{ANCHOR_DISCRIMINATOR_SIZE, PORTAL_PROGRAM, INDEX_SCALE_F64},
2121
errors::EarnError,
2222
state::{EarnGlobal, GLOBAL_SEED, TOKEN_AUTHORITY_SEED},
2323
utils::{conversion::update_multiplier, token::thaw_token_account},
@@ -27,7 +27,6 @@ cfg_if::cfg_if!(
2727
if #[cfg(feature = "migrate")] {
2828
declare_program!(old_earn);
2929
use old_earn::{accounts::Global as OldGlobal, ID as OLD_EARN_PROGRAM_ID};
30-
3130
use crate::utils::conversion::{get_scaled_ui_config, principal_to_amount_up};
3231
}
3332
);
@@ -59,7 +58,7 @@ pub struct Initialize<'info> {
5958

6059
#[account(
6160
mut,
62-
mint::token_program = token_program
61+
mint::token_program = token_program,
6362
mint::decimals = 6, // Must be 6 decimals
6463
)]
6564
pub m_mint: InterfaceAccount<'info, Mint>,
@@ -113,7 +112,7 @@ pub struct Initialize<'info> {
113112
}
114113

115114
impl Initialize<'_> {
116-
fn validate(&self) -> Result<()> {
115+
fn validate(&self, _current_index: u64) -> Result<()> {
117116
// Get the mint account data once and reuse it
118117
let account_info = self.m_mint.to_account_info();
119118
let mint_data = account_info.try_borrow_data()?;
@@ -133,6 +132,23 @@ impl Initialize<'_> {
133132
return err!(EarnError::InvalidMint);
134133
}
135134

135+
// Verify that the new multiplier is less than or equal to the current index (if migrating) or provided index (if not migrating)
136+
// This is required because the call to our update_multiplier fn will fail silently if the multiplier on the mint is greater.
137+
// That behavior is desired except when initializing the program. Therefore, we catch the error here.
138+
let current_multiplier: f64;
139+
let mint_multiplier: f64 = scaled_ui_config.new_multiplier.into();
140+
cfg_if! {
141+
if #[cfg(feature = "migrate")] {
142+
current_multiplier = self.old_global_account.index as f64 / INDEX_SCALE_F64;
143+
144+
} else {
145+
current_multiplier = _current_index as f64 / INDEX_SCALE_F64;
146+
}
147+
}
148+
if mint_multiplier > current_multiplier {
149+
return err!(EarnError::InvalidMint);
150+
}
151+
136152
// 2. Must have the Default Account State extension
137153
// and the global account as the freeze authority
138154
if !extensions.contains(&ExtensionType::DefaultAccountState) {
@@ -168,7 +184,7 @@ impl Initialize<'_> {
168184
Ok(())
169185
}
170186

171-
#[access_control(ctx.accounts.validate())]
187+
#[access_control(ctx.accounts.validate(_current_index))]
172188
pub fn handler(ctx: Context<Initialize>, _current_index: u64) -> Result<()> {
173189
// Set global state
174190
ctx.accounts.global_account.set_inner(EarnGlobal {

tests/unit/portal.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ describe('Portal unit tests', () => {
279279
});
280280
test('initialize earn', async () => {
281281
await earn.methods
282-
.initialize(new BN(100_000_000))
282+
.initialize(new BN(1e12))
283283
.accounts({
284284
admin: admin.publicKey,
285285
mMint: mint.publicKey,

0 commit comments

Comments
 (0)