update
This commit is contained in:
parent
31ceb4e22e
commit
a910d583c6
|
@ -30,6 +30,7 @@ pub mod cfo {
|
||||||
registrar: Pubkey,
|
registrar: Pubkey,
|
||||||
msrm_registrar: Pubkey,
|
msrm_registrar: Pubkey,
|
||||||
swap_interval: i64,
|
swap_interval: i64,
|
||||||
|
max_swap_usdc: u64,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let officer = &mut ctx.accounts.officer;
|
let officer = &mut ctx.accounts.officer;
|
||||||
officer.authority = *ctx.accounts.authority.key;
|
officer.authority = *ctx.accounts.authority.key;
|
||||||
|
@ -43,6 +44,7 @@ pub mod cfo {
|
||||||
officer.srm_vault = *ctx.accounts.srm_vault.to_account_info().key;
|
officer.srm_vault = *ctx.accounts.srm_vault.to_account_info().key;
|
||||||
officer.bumps = bumps;
|
officer.bumps = bumps;
|
||||||
officer.swap_interval = swap_interval;
|
officer.swap_interval = swap_interval;
|
||||||
|
officer.max_swap_usdc = max_swap_usdc;
|
||||||
emit!(OfficerDidCreate {
|
emit!(OfficerDidCreate {
|
||||||
pubkey: *officer.to_account_info().key,
|
pubkey: *officer.to_account_info().key,
|
||||||
});
|
});
|
||||||
|
@ -114,18 +116,34 @@ pub mod cfo {
|
||||||
ctx.accounts.market_auth.last_trade = Clock::get()?.unix_timestamp;
|
ctx.accounts.market_auth.last_trade = Clock::get()?.unix_timestamp;
|
||||||
|
|
||||||
// Trade.
|
// Trade.
|
||||||
let seeds = [
|
let amount_traded_usdc = {
|
||||||
ctx.accounts.dex_program.key.as_ref(),
|
// USDC before the swap.
|
||||||
&[ctx.accounts.officer.bumps.bump],
|
let usdc_before = ctx.accounts.usdc_vault.amount;
|
||||||
];
|
|
||||||
let cpi_ctx = CpiContext::from(&*ctx.accounts);
|
// Swap..
|
||||||
swap::cpi::swap(
|
let seeds = [
|
||||||
cpi_ctx.with_signer(&[&seeds]),
|
ctx.accounts.dex_program.key.as_ref(),
|
||||||
swap::Side::Ask,
|
&[ctx.accounts.officer.bumps.bump],
|
||||||
ctx.accounts.from_vault.amount,
|
];
|
||||||
min_exchange_rate.into(),
|
let cpi_ctx = CpiContext::from(&*ctx.accounts);
|
||||||
)
|
swap::cpi::swap(
|
||||||
.map_err(Into::into)
|
cpi_ctx.with_signer(&[&seeds]),
|
||||||
|
swap::Side::Ask,
|
||||||
|
ctx.accounts.from_vault.amount,
|
||||||
|
min_exchange_rate.into(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// USDC after the swap.
|
||||||
|
ctx.accounts.usdc_vault.reload()?;
|
||||||
|
ctx.accounts.usdc_vault.amount - usdc_before
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reject any swap over the max size.
|
||||||
|
if amount_traded_usdc > ctx.accounts.officer.max_swap_usdc {
|
||||||
|
return Err(ErrorCode::SwapTooLarge.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the CFO's entire token balance into SRM.
|
/// Convert the CFO's entire token balance into SRM.
|
||||||
|
@ -151,10 +169,14 @@ pub mod cfo {
|
||||||
swap::cpi::swap(
|
swap::cpi::swap(
|
||||||
cpi_ctx.with_signer(&[&seeds]),
|
cpi_ctx.with_signer(&[&seeds]),
|
||||||
swap::Side::Bid,
|
swap::Side::Bid,
|
||||||
ctx.accounts.usdc_vault.amount,
|
std::cmp::min(
|
||||||
|
ctx.accounts.usdc_vault.amount,
|
||||||
|
ctx.accounts.officer.max_swap_usdc,
|
||||||
|
),
|
||||||
min_exchange_rate.into(),
|
min_exchange_rate.into(),
|
||||||
)
|
)?;
|
||||||
.map_err(Into::into)
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Distributes srm tokens to the various categories. Before calling this,
|
/// Distributes srm tokens to the various categories. Before calling this,
|
||||||
|
@ -694,6 +716,8 @@ pub struct Officer {
|
||||||
pub authority: Pubkey,
|
pub authority: Pubkey,
|
||||||
// Required trade interval in seconds.
|
// Required trade interval in seconds.
|
||||||
pub swap_interval: i64,
|
pub swap_interval: i64,
|
||||||
|
// Maximum amount of native USDC that can be swapped in one tx.
|
||||||
|
pub max_swap_usdc: u64,
|
||||||
// Vault holding the officer's SRM tokens prior to distribution.
|
// Vault holding the officer's SRM tokens prior to distribution.
|
||||||
pub srm_vault: Pubkey,
|
pub srm_vault: Pubkey,
|
||||||
// Escrow SRM vault holding tokens which are dropped onto stakers.
|
// Escrow SRM vault holding tokens which are dropped onto stakers.
|
||||||
|
@ -935,6 +959,8 @@ pub enum ErrorCode {
|
||||||
InsufficientStakeReward,
|
InsufficientStakeReward,
|
||||||
#[msg("Swap interval must pass before another trade can occur")]
|
#[msg("Swap interval must pass before another trade can occur")]
|
||||||
SwapIntervalBlocked,
|
SwapIntervalBlocked,
|
||||||
|
#[msg("Swap too large")]
|
||||||
|
SwapTooLarge,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Access control.
|
// Access control.
|
||||||
|
|
|
@ -28,6 +28,7 @@ const SYSVAR_INSTRUCTIONS_PUBKEY = new PublicKey(
|
||||||
);
|
);
|
||||||
const FEES = "6160355581";
|
const FEES = "6160355581";
|
||||||
const SWAP_INTERVAL = new anchor.BN(1);
|
const SWAP_INTERVAL = new anchor.BN(1);
|
||||||
|
const MAX_SWAP_USDC = new anchor.BN(50000000000);
|
||||||
|
|
||||||
describe("cfo", () => {
|
describe("cfo", () => {
|
||||||
anchor.setProvider(anchor.Provider.env());
|
anchor.setProvider(anchor.Provider.env());
|
||||||
|
@ -127,9 +128,23 @@ describe("cfo", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("BOILERPLATE: Sets up the staking pools", async () => {
|
it("BOILERPLATE: Sets up the staking pools", async () => {
|
||||||
await setupStakePool(ORDERBOOK_ENV.mintA, ORDERBOOK_ENV.godA);
|
const {
|
||||||
registrar = ORDERBOOK_ENV.usdc;
|
registrar: _registrar,
|
||||||
msrmRegistrar = registrar;
|
rewardEventQ: _rewardEventQ,
|
||||||
|
poolMint: _poolMint,
|
||||||
|
} = await setupStakePool(ORDERBOOK_ENV.mintA, ORDERBOOK_ENV.godA);
|
||||||
|
const {
|
||||||
|
registrar: _msrmRegistrar,
|
||||||
|
rewardEventQ: _msrmRewardEventQ,
|
||||||
|
poolMint: _msrmPoolMint,
|
||||||
|
} = await setupStakePool(ORDERBOOK_ENV.mintB, ORDERBOOK_ENV.godB);
|
||||||
|
|
||||||
|
registrar = _registrar;
|
||||||
|
rewardEventQ = _rewardEventQ;
|
||||||
|
poolMint = _poolMint;
|
||||||
|
msrmRegistrar = _msrmRegistrar;
|
||||||
|
msrmRewardEventQ = _msrmRewardEventQ;
|
||||||
|
msrmPoolMint = _msrmPoolMint;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("BOILERPLATE: Finds PDA addresses", async () => {
|
it("BOILERPLATE: Finds PDA addresses", async () => {
|
||||||
|
@ -243,6 +258,7 @@ describe("cfo", () => {
|
||||||
registrar,
|
registrar,
|
||||||
msrmRegistrar,
|
msrmRegistrar,
|
||||||
SWAP_INTERVAL,
|
SWAP_INTERVAL,
|
||||||
|
MAX_SWAP_USDC,
|
||||||
{
|
{
|
||||||
accounts: {
|
accounts: {
|
||||||
officer,
|
officer,
|
||||||
|
|
|
@ -161,6 +161,13 @@ async function setupStakePool(mint, god) {
|
||||||
tokenProgram: TokenInstructions.TOKEN_PROGRAM_ID,
|
tokenProgram: TokenInstructions.TOKEN_PROGRAM_ID,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
registrar: registrar.publicKey,
|
||||||
|
poolMint,
|
||||||
|
rewardEventQ: rewardQ.publicKey,
|
||||||
|
member,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
Loading…
Reference in New Issue