Deposit: Don't add accounts to lookup table twice

This commit is contained in:
Christian Kamm 2022-02-28 20:12:12 +01:00
parent 5ebf425a65
commit 3e6d722e01
2 changed files with 22 additions and 9 deletions

View File

@ -2,6 +2,7 @@ use anchor_lang::prelude::*;
use anchor_spl::token; use anchor_spl::token;
use anchor_spl::token::Token; use anchor_spl::token::Token;
use anchor_spl::token::TokenAccount; use anchor_spl::token::TokenAccount;
use solana_program::pubkey::PUBKEY_BYTES;
use crate::solana_address_lookup_table_instruction; use crate::solana_address_lookup_table_instruction;
use crate::state::*; use crate::state::*;
@ -51,11 +52,22 @@ impl<'info> Deposit<'info> {
} }
} }
fn address_lookup_table_contains(table: &AccountInfo, pubkey: &Pubkey) -> Result<bool> {
let table_data = table.try_borrow_data()?;
let pk_ref = pubkey.as_ref();
Ok(
table_data[solana_address_lookup_table_instruction::LOOKUP_TABLE_META_SIZE..]
.chunks(PUBKEY_BYTES)
.find(|&d| d == pk_ref)
.is_some(),
)
}
// TODO: It may make sense to have the token_index passed in from the outside. // TODO: It may make sense to have the token_index passed in from the outside.
// That would save a lot of computation that needs to go into finding the // That would save a lot of computation that needs to go into finding the
// right index for the mint. // right index for the mint.
pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> { pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
let (is_new, oracle) = { let (is_new_position, oracle) = {
// Find the mint's token index // Find the mint's token index
let group = ctx.accounts.group.load()?; let group = ctx.accounts.group.load()?;
let mint = ctx.accounts.token_account.mint; let mint = ctx.accounts.token_account.mint;
@ -64,7 +76,7 @@ pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
// Get the account's position for that token index // Get the account's position for that token index
let mut account = ctx.accounts.account.load_mut()?; let mut account = ctx.accounts.account.load_mut()?;
let position = account.indexed_positions.get_mut_or_create(token_index)?; let position = account.indexed_positions.get_mut_or_create(token_index)?;
let is_new = !position.is_active(); let is_new_position = !position.is_active();
// Update the bank and position // Update the bank and position
let mut bank = ctx.accounts.bank.load_mut()?; let mut bank = ctx.accounts.bank.load_mut()?;
@ -73,14 +85,15 @@ pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
// Transfer the actual tokens // Transfer the actual tokens
token::transfer(ctx.accounts.transfer_ctx(), amount)?; token::transfer(ctx.accounts.transfer_ctx(), amount)?;
(is_new, bank.oracle) (is_new_position, bank.oracle)
}; };
// TODO: Also check if these accounts are already on the table? Otherwise a deposit-withdraw // Do we need to add (oracle, bank) to the user's address lookup table?
// cycle would quickly fill up the lookup table with the same two accounts! //
if is_new { // Since they are always added as a pair, checking for one is sufficient.
// Add the bank and oracle to the address map let add_to_lookup_table = is_new_position
// && !address_lookup_table_contains(&ctx.accounts.address_lookup_table, &oracle)?;
if add_to_lookup_table {
// NOTE: Unfortunately extend() _requires_ a payer, even though we've already // NOTE: Unfortunately extend() _requires_ a payer, even though we've already
// fully funded the address lookup table. No further transfer will be necessary. // fully funded the address lookup table. No further transfer will be necessary.
// We'll pass the account as payer. // We'll pass the account as payer.

View File

@ -25,7 +25,7 @@ pub const LOOKUP_TABLE_MAX_ADDRESSES: usize = 256;
pub const LOOKUP_TABLE_META_SIZE: usize = 56; pub const LOOKUP_TABLE_META_SIZE: usize = 56;
pub const LOOKUP_TABLE_MAX_ACCOUNT_SIZE: usize = pub const LOOKUP_TABLE_MAX_ACCOUNT_SIZE: usize =
LOOKUP_TABLE_META_SIZE + LOOKUP_TABLE_MAX_ADDRESSES * 32; LOOKUP_TABLE_META_SIZE + LOOKUP_TABLE_MAX_ADDRESSES * solana_program::pubkey::PUBKEY_BYTES;
// NOTE: Manual additions end // NOTE: Manual additions end
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]