Token deposit: Require valid oracle for new token positions (#722)
This avoids making an account accidentally or intentionally unusable (except for deposits/withdraws) by depositing a token with a stale oracle.
This commit is contained in:
parent
9b224eae1b
commit
2c4009eab1
|
@ -179,7 +179,28 @@ pub fn token_deposit(ctx: Context<TokenDeposit>, amount: u64, reduce_only: bool)
|
|||
{
|
||||
let token_index = ctx.accounts.bank.load()?.token_index;
|
||||
let mut account = ctx.accounts.account.load_full_mut()?;
|
||||
account.ensure_token_position(token_index)?;
|
||||
|
||||
let token_position_exists = account
|
||||
.all_token_positions()
|
||||
.any(|p| p.is_active_for_token(token_index));
|
||||
|
||||
// Activating a new token position requires that the oracle is in a good state.
|
||||
// Otherwise users could abuse oracle staleness to delay liquidation.
|
||||
if !token_position_exists {
|
||||
let now_slot = Clock::get()?.slot;
|
||||
let bank = ctx.accounts.bank.load()?;
|
||||
|
||||
let oracle_result = bank.oracle_price(
|
||||
&AccountInfoRef::borrow(ctx.accounts.oracle.as_ref())?,
|
||||
Some(now_slot),
|
||||
);
|
||||
if let Err(e) = oracle_result {
|
||||
msg!("oracle must be valid when creating a new token position");
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
account.ensure_token_position(token_index)?;
|
||||
}
|
||||
}
|
||||
|
||||
DepositCommon {
|
||||
|
|
|
@ -67,7 +67,7 @@ async fn test_stale_oracle_deposit_withdraw() -> Result<(), TransportError> {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
// Make both oracles invalid by increasing deviation
|
||||
// Make oracles invalid by increasing deviation
|
||||
send_tx(
|
||||
solana,
|
||||
StubOracleSetTestInstruction {
|
||||
|
@ -94,6 +94,35 @@ async fn test_stale_oracle_deposit_withdraw() -> Result<(), TransportError> {
|
|||
)
|
||||
.await
|
||||
.unwrap();
|
||||
send_tx(
|
||||
solana,
|
||||
StubOracleSetTestInstruction {
|
||||
group,
|
||||
mint: mints[2].pubkey,
|
||||
admin,
|
||||
price: 1.0,
|
||||
last_update_slot: 0,
|
||||
deviation: 100.0,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Can't activate a token position for a bad oracle
|
||||
assert!(send_tx(
|
||||
solana,
|
||||
TokenDepositInstruction {
|
||||
amount: 11,
|
||||
reduce_only: false,
|
||||
account,
|
||||
owner,
|
||||
token_account: payer_token_accounts[2],
|
||||
token_authority: payer.clone(),
|
||||
bank_index: 0,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.is_err());
|
||||
|
||||
// Verify that creating a new borrow won't work
|
||||
assert!(send_tx(
|
||||
|
|
Loading…
Reference in New Issue