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

MarketUpdated event #1697

Merged
merged 10 commits into from
Jul 5, 2023
5 changes: 5 additions & 0 deletions markets/perps-market/cannonfile.test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ artifact = "PerpsMarketFactoryModule"
[contract.AsyncOrderModule]
artifact = "AsyncOrderModule"

[contract.AsyncOrderViewModule]
artifact = "AsyncOrderViewModule"

[contract.AtomicOrderModule]
artifact = "AtomicOrderModule"

Expand Down Expand Up @@ -73,6 +76,7 @@ contracts = [
"PerpsMarketModule",
"AtomicOrderModule",
"AsyncOrderModule",
"AsyncOrderViewModule",
"FeatureFlagModule",
"LimitOrderModule",
"LiquidationModule",
Expand All @@ -85,6 +89,7 @@ depends = [
"contract.PerpsMarketFactoryModule",
"contract.AtomicOrderModule",
"contract.AsyncOrderModule",
"contract.AsyncOrderViewModule",
"contract.PerpsAccountModule",
"contract.PerpsMarketModule",
"contract.FeatureFlagModule",
Expand Down
5 changes: 5 additions & 0 deletions markets/perps-market/cannonfile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ artifact = "PerpsMarketFactoryModule"
[contract.AsyncOrderModule]
artifact = "AsyncOrderModule"

[contract.AsyncOrderViewModule]
artifact = "AsyncOrderViewModule"

[contract.AtomicOrderModule]
artifact = "AtomicOrderModule"

Expand Down Expand Up @@ -73,6 +76,7 @@ contracts = [
"PerpsMarketModule",
"AtomicOrderModule",
"AsyncOrderModule",
"AsyncOrderViewModule",
"FeatureFlagModule",
"LimitOrderModule",
"LiquidationModule",
Expand All @@ -85,6 +89,7 @@ depends = [
"contract.PerpsMarketFactoryModule",
"contract.AtomicOrderModule",
"contract.AsyncOrderModule",
"contract.AsyncOrderViewModule",
"contract.PerpsAccountModule",
"contract.PerpsMarketModule",
"contract.FeatureFlagModule",
Expand Down
14 changes: 9 additions & 5 deletions markets/perps-market/contracts/interfaces/IAsyncOrderModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ interface IAsyncOrderModule {
uint256 acceptablePrice
);

event MarketUpdated(
uint128 marketId,
int256 skew,
uint256 size,
int256 sizeDelta,
int256 currentFundingRate,
int256 currentFundingVelocity
);

error OrderAlreadyCommitted(uint128 marketId, uint128 accountId);
error SettlementStrategyNotFound(SettlementStrategy.Type strategyType);
error OffchainLookup(
Expand Down Expand Up @@ -66,9 +75,4 @@ interface IAsyncOrderModule {
uint256 settlementReward;
bytes32 trackingCode;
}

function getOrder(
uint128 marketId,
uint128 accountId
) external returns (AsyncOrder.Data memory);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

import {AsyncOrder} from "../storage/AsyncOrder.sol";

/**
* @title Module for view methods realted to async orders
*/
interface IAsyncOrderViewModule {
function getOrder(
uint128 marketId,
uint128 accountId
) external returns (AsyncOrder.Data memory);
}
14 changes: 4 additions & 10 deletions markets/perps-market/contracts/modules/AsyncOrderModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,6 @@ contract AsyncOrderModule is IAsyncOrderModule {
_settleOrder(offchainPrice, order, settlementStrategy);
}

function getOrder(
uint128 marketId,
uint128 accountId
) public view override returns (AsyncOrder.Data memory) {
return PerpsMarket.loadValid(marketId).asyncOrders[accountId];
}

function cancelOrder(uint128 marketId, uint128 accountId) external override {
AsyncOrder.Data storage order = PerpsMarket.loadValid(marketId).asyncOrders[accountId];
order.checkValidity();
Expand Down Expand Up @@ -205,7 +198,8 @@ contract AsyncOrderModule is IAsyncOrderModule {
}

// after pnl is realized, update position
PerpsMarket.loadValid(runtime.marketId).updatePositionData(runtime.accountId, newPosition);
PerpsMarket.Data storage market = PerpsMarket.loadValid(runtime.marketId);
market.updatePositionData(runtime.accountId, newPosition);

perpsAccount.updatePositionMarkets(runtime.marketId, runtime.newPositionSize);
perpsAccount.deductFromAccount(totalFees);
Expand All @@ -223,7 +217,7 @@ contract AsyncOrderModule is IAsyncOrderModule {
}

// exctracted from asyncOrder before order is reset
bytes32 trackingCode = asyncOrder.trackingCode;
runtime.trackingCode = asyncOrder.trackingCode;

asyncOrder.reset();

Expand All @@ -236,7 +230,7 @@ contract AsyncOrderModule is IAsyncOrderModule {
runtime.newPositionSize,
totalFees,
runtime.settlementReward,
trackingCode,
runtime.trackingCode,
msg.sender
);
}
Expand Down
17 changes: 17 additions & 0 deletions markets/perps-market/contracts/modules/AsyncOrderViewModule.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

import {IAsyncOrderViewModule} from "../interfaces/IAsyncOrderViewModule.sol";
import {AsyncOrder} from "../storage/AsyncOrder.sol";
import {PerpsMarket} from "../storage/PerpsMarket.sol";

contract AsyncOrderViewModule is IAsyncOrderViewModule {
0xjocke marked this conversation as resolved.
Show resolved Hide resolved
using PerpsMarket for PerpsMarket.Data;

function getOrder(
uint128 marketId,
uint128 accountId
) public view override returns (AsyncOrder.Data memory) {
return PerpsMarket.loadValid(marketId).asyncOrders[accountId];
}
}
1 change: 1 addition & 0 deletions markets/perps-market/contracts/storage/AsyncOrder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ library AsyncOrder {
uint initialRequiredMargin;
uint totalRequiredMargin;
Position.Data newPosition;
bytes32 trackingCode;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, without it we get "Stack too deep." Just at the limit now 😓

}

function validateOrder(
Expand Down
19 changes: 19 additions & 0 deletions markets/perps-market/contracts/storage/PerpsMarket.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ library PerpsMarket {

error PriceFeedNotSet(uint128 marketId);

event MarketUpdated(
0xjocke marked this conversation as resolved.
Show resolved Hide resolved
uint128 marketId,
int256 skew,
uint256 size,
int256 sizeDelta,
int256 currentFundingRate,
int256 currentFundingVelocity
);

struct Data {
address owner;
address nominatedOwner;
Expand Down Expand Up @@ -144,6 +153,16 @@ library PerpsMarket {
self.size = (self.size + MathUtil.abs(newPosition.size)) - MathUtil.abs(oldPositionSize);
self.skew += newPosition.size - oldPositionSize;
oldPosition.updatePosition(newPosition);
int128 sizeDelta = newPosition.size - oldPositionSize;
// TODO add current market debt
emit MarketUpdated(
self.id,
self.skew,
self.size,
sizeDelta,
currentFundingRate(self),
currentFundingVelocity(self)
0xjocke marked this conversation as resolved.
Show resolved Hide resolved
);
0xjocke marked this conversation as resolved.
Show resolved Hide resolved
}

function loadWithVerifiedOwner(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import assertBn from '@synthetixio/core-utils/utils/assertions/assert-bignumber'
import assertEvent from '@synthetixio/core-utils/utils/assertions/assert-event';
import assertRevert from '@synthetixio/core-utils/utils/assertions/assert-revert';
import { getTxTime } from '@synthetixio/core-utils/src/utils/hardhat/rpc';
import { wei } from '@synthetixio/wei';
import { calcCurrentFundingVelocity } from '../helpers/funding-calcs';

describe('Settle Offchain Async Order test', () => {
const { systems, perpsMarkets, synthMarkets, provider, trader1, keeper } = bootstrapMarkets({
Expand All @@ -24,7 +26,7 @@ describe('Settle Offchain Async Order test', () => {
name: 'Ether',
token: 'snxETH',
price: bn(1000),
fundingParams: { skewScale: bn(100_000), maxFundingVelocity: bn(0) },
fundingParams: { skewScale: bn(100_000), maxFundingVelocity: bn(10) },
},
],
traderAccountIds: [2, 3],
Expand Down Expand Up @@ -379,16 +381,56 @@ describe('Settle Offchain Async Order test', () => {
.settlePythOrder(pythPriceData, extraData, { value: updateFee });
});

it('emits event', async () => {
it('emits event settle event', async () => {
// TODO Calculate the correct fill price instead of hardcoding

const accountId = 2;
const fillPrice = bn(1000.005);
const pnl = 0;
const newPositionSize = bn(1);
const totalFees = DEFAULT_SETTLEMENT_STRATEGY.settlementReward;
const settlementReward = DEFAULT_SETTLEMENT_STRATEGY.settlementReward;
const trackingCode = `"${ethers.constants.HashZero}"`;
const msgSender = `"${await keeper().getAddress()}"`;
const params = [
ethMarketId,
accountId,
fillPrice,
pnl,
newPositionSize,
totalFees,
settlementReward,
trackingCode,
msgSender,
];
await assertEvent(
settleTx,
`OrderSettled(${params.join(', ')})`,
systems().PerpsMarket
);
});

it('emits market updated event', async () => {
const marketSize = bn(1);
const marketSkew = bn(1);
const sizeDelta = bn(1);
const currentFundingRate = bn(0);
const currentFundingVelocity = calcCurrentFundingVelocity({
skew: wei(1),
skewScale: wei(100_000),
maxFundingVelocity: wei(10),
});
const params = [
ethMarketId,
marketSkew,
marketSize,
sizeDelta,
currentFundingRate,
currentFundingVelocity.toBN(), // Funding rates should be tested more thoroughly elsewhre
];
await assertEvent(
settleTx,
`OrderSettled(${ethMarketId}, 2, ${fillPrice}, 0, ${bn(1)}, ${
DEFAULT_SETTLEMENT_STRATEGY.settlementReward
}, ${DEFAULT_SETTLEMENT_STRATEGY.settlementReward}, "${
ethers.constants.HashZero
}", "${await keeper().getAddress()}")`,
`MarketUpdated(${params.join(', ')})`,
systems().PerpsMarket
);
});
Expand Down
22 changes: 22 additions & 0 deletions markets/perps-market/test/integration/helpers/funding-calcs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Wei, { wei } from '@synthetixio/wei';

export function calcCurrentFundingVelocity({
skew,
skewScale,
maxFundingVelocity,
}: {
skew: Wei;
skewScale: Wei;
maxFundingVelocity: Wei;
}) {
// Avoid a panic due to div by zero. Return 0 immediately.
if (skewScale.eq(0)) {
return wei(0);
}

// Ensures the proportionalSkew is between -1 and 1.
const pSkew = wei(skew).div(skewScale);
const pSkewBounded = Wei.max(Wei.min(pSkew, wei(1)), wei(-1));

return pSkewBounded.mul(maxFundingVelocity);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe returns bignumber via .toBN() here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coming from the frontend we usually keep everything in Wei and just toBN before sending to ethers contract call. Wei usually makes math and most things easier.
But we do seem to like/use BigNumber more in contract tests, so I guess it make sense to return bn.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok cool yeah fair enough!

}
Loading