Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Additional checks for closing orders/settling markets #21

Merged
merged 3 commits into from
Feb 16, 2023
Merged
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
8 changes: 8 additions & 0 deletions programs/monaco_protocol/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,14 @@ pub struct UpdateMarket<'info> {
pub struct CompleteMarketSettlement<'info> {
#[account(mut)]
pub market: Account<'info, Market>,
#[account(
mut,
token::mint = market.mint_account,
token::authority = market_escrow,
seeds = [b"escrow".as_ref(), market.key().as_ref()],
bump,
)]
pub market_escrow: Box<Account<'info, TokenAccount>>,

#[account(mut)]
pub crank_operator: Signer<'info>,
Expand Down
4 changes: 4 additions & 0 deletions programs/monaco_protocol/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ pub enum CoreError {
SettlementMarketNotSettled,
#[msg("Core Settlement: market not ready for settlement")]
SettlementMarketNotReadyForSettlement,
#[msg("Core Settlement: market escrow is non zero")]
SettlementMarketEscrowNonZero,

/*
Authorised Operator
Expand Down Expand Up @@ -180,6 +182,8 @@ pub enum CoreError {
/*
Close Account
*/
#[msg("CloseAccount: Order not complete")]
CloseAccountOrderNotComplete,
#[msg("CloseAccount: Purchaser does not match")]
CloseAccountPurchaserMismatch,
#[msg("CloseAccount: Market does not match")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ pub fn settle(
}

pub fn complete_settlement(ctx: Context<CompleteMarketSettlement>) -> Result<()> {
require!(
ctx.accounts.market_escrow.amount == 0_u64,
CoreError::SettlementMarketEscrowNonZero
);

let market = &mut ctx.accounts.market;
require!(
ReadyForSettlement.eq(&market.market_status),
Expand Down
5 changes: 5 additions & 0 deletions programs/monaco_protocol/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,11 @@ pub mod monaco_protocol {
CoreError::MarketNotReadyToClose
);

require!(
ctx.accounts.order.is_completed(),
CoreError::CloseAccountOrderNotComplete
);

Ok(())
}

Expand Down
46 changes: 46 additions & 0 deletions tests/market/update_market_status.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import assert from "assert";
import { monaco } from "../util/wrappers";
import { createWalletWithBalance } from "../util/test_util";

describe("Market: update status", () => {
it("Settle market", async () => {
Expand Down Expand Up @@ -71,6 +72,7 @@ describe("Market: update status", () => {
.completeMarketSettlement()
.accounts({
market: market.pk,
marketEscrow: market.escrowPk,
authorisedOperators: await monaco.findCrankAuthorisedOperatorsPda(),
crankOperator: monaco.operatorPk,
})
Expand All @@ -84,6 +86,50 @@ describe("Market: update status", () => {
assert.deepEqual(marketAccount.marketStatus, { settled: {} });
});

it("Complete market settlement fails when escrow is non-zero", async () => {
// create a new market and purchaser
const [market, purchaser] = await Promise.all([
monaco.create3WayMarket([4.2]),
createWalletWithBalance(monaco.provider),
]);
await market.airdrop(purchaser, 100.0);

// This order is never matched or cancelled or settled
await market.forOrder(0, 1, 4.2, purchaser);

await monaco.program.methods
.settleMarket(1)
.accounts({
market: market.pk,
authorisedOperators: await monaco.findMarketAuthorisedOperatorsPda(),
marketOperator: monaco.operatorPk,
})
.rpc()
.catch((e) => {
console.error(e);
throw e;
});

let marketAccount = await monaco.fetchMarket(market.pk);
assert.deepEqual(marketAccount.marketStatus, { readyForSettlement: {} });

await monaco.program.methods
.completeMarketSettlement()
.accounts({
market: market.pk,
marketEscrow: market.escrowPk,
authorisedOperators: await monaco.findCrankAuthorisedOperatorsPda(),
crankOperator: monaco.operatorPk,
})
.rpc()
.catch((e) => {
assert.equal(e.error.errorCode.code, "SettlementMarketEscrowNonZero");
});

marketAccount = await monaco.fetchMarket(market.pk);
assert.deepEqual(marketAccount.marketStatus, { readyForSettlement: {} });
});

it("Publish and unpublish", async () => {
// create a new market
const market = await monaco.create3WayMarket([4.2]);
Expand Down
1 change: 1 addition & 0 deletions tests/util/wrappers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,7 @@ export class MonacoMarket {
.completeMarketSettlement()
.accounts({
market: this.pk,
marketEscrow: this.escrowPk,
crankOperator: this.monaco.operatorPk,
authorisedOperators:
await this.monaco.findCrankAuthorisedOperatorsPda(),
Expand Down