-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathimprove.rs
106 lines (91 loc) · 3.24 KB
/
improve.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use crate::{
error::MatchingEngineError,
state::{Auction, AuctionConfig, Custodian},
utils,
};
use anchor_lang::prelude::*;
use anchor_spl::token;
#[derive(Accounts)]
pub struct ImproveOffer<'info> {
/// This program's Wormhole (Core Bridge) emitter authority. This is also the burn-source
/// authority for CCTP transfers.
///
/// CHECK: Seeds must be \["emitter"\].
#[account(
seeds = [Custodian::SEED_PREFIX],
bump = Custodian::BUMP,
)]
custodian: AccountInfo<'info>,
auction_config: Account<'info, AuctionConfig>,
offer_authority: Signer<'info>,
#[account(
mut,
seeds = [
Auction::SEED_PREFIX,
auction.vaa_hash.as_ref(),
],
bump = auction.bump,
constraint = utils::is_valid_active_auction(
&auction_config,
&auction,
Some(best_offer_token.key()),
None,
)?
)]
auction: Account<'info, Auction>,
#[account(
mut,
associated_token::mint = common::constants::USDC_MINT,
associated_token::authority = offer_authority
)]
offer_token: Account<'info, token::TokenAccount>,
/// CHECK: Mutable. Must have the same key in auction data.
#[account(mut)]
best_offer_token: AccountInfo<'info>,
token_program: Program<'info, token::Token>,
}
pub fn improve_offer(ctx: Context<ImproveOffer>, fee_offer: u64) -> Result<()> {
let auction_info = ctx.accounts.auction.info.as_mut().unwrap();
{
let current_slot = Clock::get().map(|clock| clock.slot)?;
require!(
current_slot <= auction_info.auction_end_slot(&ctx.accounts.auction_config),
MatchingEngineError::AuctionPeriodExpired
);
}
// Make sure the new offer is less than the previous offer.
require!(
fee_offer < auction_info.offer_price,
MatchingEngineError::OfferPriceNotImproved
);
// This check is safe because we already checked that `fee_offer` is less than `offer_price`.
{
let min_offer_delta =
utils::auction::compute_min_offer_delta(&ctx.accounts.auction_config, auction_info);
require!(
auction_info.offer_price - fee_offer >= min_offer_delta,
MatchingEngineError::CarpingNotAllowed
);
}
// Transfer funds from the `offer_token` token account to the `best_offer_token` token account,
// but only if the pubkeys are different.
let offer_token = ctx.accounts.offer_token.key();
if auction_info.best_offer_token != offer_token {
token::transfer(
CpiContext::new_with_signer(
ctx.accounts.token_program.to_account_info(),
anchor_spl::token::Transfer {
from: ctx.accounts.offer_token.to_account_info(),
to: ctx.accounts.best_offer_token.to_account_info(),
authority: ctx.accounts.custodian.to_account_info(),
},
&[Custodian::SIGNER_SEEDS],
),
auction_info.total_deposit(),
)?;
// Update the `best_offer` token account and `amount` fields.
auction_info.best_offer_token = offer_token;
}
auction_info.offer_price = fee_offer;
Ok(())
}