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
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,9 @@ pub struct SettingsChangePolicyEvent {
pub settings: Settings,
pub changes: Vec<LimitedSettingsAction>,
}

#[derive(BorshSerialize, BorshDeserialize)]
pub struct SetAccountIndexEvent {
pub settings: Settings,
pub settings_pubkey: Pubkey,
}
1 change: 1 addition & 0 deletions programs/squads_smart_account_program/src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub enum SmartAccountEvent {
SynchronousTransactionEventV2(SynchronousTransactionEventV2),
SettingsChangePolicyEvent(SettingsChangePolicyEvent),
PolicyEvent(PolicyEvent),
SetAccountIndexEvent(SetAccountIndexEvent),
}
pub struct LogAuthorityInfo<'info> {
pub authority: AccountInfo<'info>,
Expand Down
2 changes: 2 additions & 0 deletions programs/squads_smart_account_program/src/instructions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub use transaction_execute::*;
pub use transaction_execute_sync::*;
pub use transaction_execute_sync_legacy::*;
pub use use_spending_limit::*;
pub use set_account_index::*;

mod activate_proposal;
mod authority_settings_transaction_execute;
Expand Down Expand Up @@ -51,3 +52,4 @@ mod transaction_execute;
mod transaction_execute_sync;
mod transaction_execute_sync_legacy;
mod use_spending_limit;
mod set_account_index;
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use anchor_lang::prelude::*;
use anchor_lang::solana_program::pubkey;

use crate::{
errors::SmartAccountError,
events::*,
program::SquadsSmartAccountProgram,
state::{Settings, SEED_PREFIX, SEED_SETTINGS, get_settings_signer_seeds},
};

pub const FREE_ACCOUNT_MAX_INDEX: u8 = 249;

#[cfg(not(feature = "testing"))]
const PAYMASTER: Pubkey = pubkey!("7kEydiJ9en86ESNpwpZ45khxX8usgjUmWxbSTzkSbXkR");

#[cfg(feature = "testing")]
const PAYMASTER: Pubkey = pubkey!("BHpoHAaFDFPwDP47mcpy2R4fXX66NsUe8y8RFkfrEMNG");

#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct SetAccountIndexArgs {
pub new_index: u8,
}

#[derive(Accounts)]
pub struct SetAccountIndex<'info> {
#[account(
mut,
seeds = [
SEED_PREFIX,
SEED_SETTINGS,
&settings.seed.to_le_bytes(),
],
bump = settings.bump,
)]
pub settings: Account<'info, Settings>,

#[account(
address = PAYMASTER @ SmartAccountError::Unauthorized
)]
pub paymaster: Signer<'info>,

pub program: Program<'info, SquadsSmartAccountProgram>,
}

impl SetAccountIndex<'_> {
fn validate(&self, args: &SetAccountIndexArgs) -> Result<()> {
require!(
args.new_index <= FREE_ACCOUNT_MAX_INDEX,
SmartAccountError::InvalidInstructionArgs
);
Ok(())
}

#[access_control(ctx.accounts.validate(&args))]
pub fn set_account_index(ctx: Context<Self>, args: SetAccountIndexArgs) -> Result<()> {
let settings = &mut ctx.accounts.settings;
settings.account_utilization = args.new_index;

let event = SetAccountIndexEvent {
settings: Settings::try_from_slice(&settings.try_to_vec()?)?,
settings_pubkey: settings.key(),
};
let log_authority_info = LogAuthorityInfo {
authority: settings.to_account_info(),
authority_seeds: get_settings_signer_seeds(settings.seed),
bump: settings.bump,
program: ctx.accounts.program.to_account_info(),
};
SmartAccountEvent::SetAccountIndexEvent(event).log(&log_authority_info)?;

Ok(())
}
}
6 changes: 6 additions & 0 deletions programs/squads_smart_account_program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,4 +340,10 @@ pub mod squads_smart_account_program {
) -> Result<()> {
LogEvent::log_event(ctx, args)
}

/// Set the account utilization index for a smart account.
/// Callable only by the paymaster key.
pub fn set_account_index(ctx: Context<SetAccountIndex>, args: SetAccountIndexArgs) -> Result<()> {
SetAccountIndex::set_account_index(ctx, args)
}
}
44 changes: 44 additions & 0 deletions sdk/smart-account/idl/squads_smart_account_program.json
Original file line number Diff line number Diff line change
Expand Up @@ -1858,6 +1858,38 @@
}
}
]
},
{
"name": "setAccountIndex",
"docs": [
"Set the account utilization index for a smart account.",
"Callable only by the paymaster key."
],
"accounts": [
{
"name": "settings",
"isMut": true,
"isSigner": false
},
{
"name": "paymaster",
"isMut": false,
"isSigner": true
},
{
"name": "program",
"isMut": false,
"isSigner": false
}
],
"args": [
{
"name": "args",
"type": {
"defined": "SetAccountIndexArgs"
}
}
]
}
],
"accounts": [
Expand Down Expand Up @@ -3114,6 +3146,18 @@
]
}
},
{
"name": "SetAccountIndexArgs",
"type": {
"kind": "struct",
"fields": [
{
"name": "newIndex",
"type": "u8"
}
]
}
},
{
"name": "CreateSettingsTransactionArgs",
"type": {
Expand Down
1 change: 1 addition & 0 deletions sdk/smart-account/src/generated/instructions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export * from './logEvent'
export * from './rejectProposal'
export * from './removeSignerAsAuthority'
export * from './removeSpendingLimitAsAuthority'
export * from './setAccountIndex'
export * from './setArchivalAuthorityAsAuthority'
export * from './setNewSettingsAuthorityAsAuthority'
export * from './setProgramConfigAuthority'
Expand Down
109 changes: 109 additions & 0 deletions sdk/smart-account/src/generated/instructions/setAccountIndex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/**
* This code was GENERATED using the solita package.
* Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality.
*
* See: https://github.com/metaplex-foundation/solita
*/

import * as beet from '@metaplex-foundation/beet'
import * as web3 from '@solana/web3.js'
import {
SetAccountIndexArgs,
setAccountIndexArgsBeet,
} from '../types/SetAccountIndexArgs'

/**
* @category Instructions
* @category SetAccountIndex
* @category generated
*/
export type SetAccountIndexInstructionArgs = {
args: SetAccountIndexArgs
}
/**
* @category Instructions
* @category SetAccountIndex
* @category generated
*/
export const setAccountIndexStruct = new beet.BeetArgsStruct<
SetAccountIndexInstructionArgs & {
instructionDiscriminator: number[] /* size: 8 */
}
>(
[
['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)],
['args', setAccountIndexArgsBeet],
],
'SetAccountIndexInstructionArgs'
)
/**
* Accounts required by the _setAccountIndex_ instruction
*
* @property [_writable_] settings
* @property [**signer**] paymaster
* @property [] program
* @category Instructions
* @category SetAccountIndex
* @category generated
*/
export type SetAccountIndexInstructionAccounts = {
settings: web3.PublicKey
paymaster: web3.PublicKey
program: web3.PublicKey
anchorRemainingAccounts?: web3.AccountMeta[]
}

export const setAccountIndexInstructionDiscriminator = [
203, 233, 20, 64, 189, 188, 245, 67,
]

/**
* Creates a _SetAccountIndex_ instruction.
*
* @param accounts that will be accessed while the instruction is processed
* @param args to provide as instruction data to the program
*
* @category Instructions
* @category SetAccountIndex
* @category generated
*/
export function createSetAccountIndexInstruction(
accounts: SetAccountIndexInstructionAccounts,
args: SetAccountIndexInstructionArgs,
programId = new web3.PublicKey('SMRTzfY6DfH5ik3TKiyLFfXexV8uSG3d2UksSCYdunG')
) {
const [data] = setAccountIndexStruct.serialize({
instructionDiscriminator: setAccountIndexInstructionDiscriminator,
...args,
})
const keys: web3.AccountMeta[] = [
{
pubkey: accounts.settings,
isWritable: true,
isSigner: false,
},
{
pubkey: accounts.paymaster,
isWritable: false,
isSigner: true,
},
{
pubkey: accounts.program,
isWritable: false,
isSigner: false,
},
]

if (accounts.anchorRemainingAccounts != null) {
for (const acc of accounts.anchorRemainingAccounts) {
keys.push(acc)
}
}

const ix = new web3.TransactionInstruction({
programId,
keys,
data,
})
return ix
}
21 changes: 21 additions & 0 deletions sdk/smart-account/src/generated/types/SetAccountIndexArgs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* This code was GENERATED using the solita package.
* Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality.
*
* See: https://github.com/metaplex-foundation/solita
*/

import * as beet from '@metaplex-foundation/beet'
export type SetAccountIndexArgs = {
newIndex: number
}

/**
* @category userTypes
* @category generated
*/
export const setAccountIndexArgsBeet =
new beet.BeetArgsStruct<SetAccountIndexArgs>(
[['newIndex', beet.u8]],
'SetAccountIndexArgs'
)
1 change: 1 addition & 0 deletions sdk/smart-account/src/generated/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export * from './ProposalStatus'
export * from './QuantityConstraints'
export * from './RemoveSignerArgs'
export * from './RemoveSpendingLimitArgs'
export * from './SetAccountIndexArgs'
export * from './SetArchivalAuthorityArgs'
export * from './SetNewSettingsAuthorityArgs'
export * from './SetTimeLockArgs'
Expand Down
1 change: 1 addition & 0 deletions tests/fixtures/paymaster-test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[49,87,162,112,58,101,205,198,205,159,92,228,246,195,192,216,22,27,112,168,116,13,3,97,109,53,41,19,44,236,23,172,152,228,53,29,45,72,43,205,72,221,144,142,193,123,101,110,114,17,216,206,37,240,242,174,168,26,164,195,235,182,43,57]
Loading