From 657cb609ba5809390bfd5a379bdca6884c396965 Mon Sep 17 00:00:00 2001 From: Flocqst Date: Mon, 20 May 2024 17:56:56 +0200 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=91=B7=20Fix=20Orderflowfee=20Notiona?= =?UTF-8?q?l=20value=20calculation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Account.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Account.sol b/src/Account.sol index aa3a0ffb..b370e4dc 100644 --- a/src/Account.sol +++ b/src/Account.sol @@ -685,7 +685,7 @@ contract Account is IAccount, Auth, OpsReady { } // calculate notional value of order - uint256 notionalValue = _abs(_sizeDelta) * price; + uint256 notionalValue = (_abs(_sizeDelta) / 1 ether) * price; // calculate fee to impose return notionalValue * orderFlowFee / SETTINGS.MAX_ORDER_FLOW_FEE(); @@ -923,7 +923,7 @@ contract Account is IAccount, Auth, OpsReady { execAddress: address(this), execData: abi.encodeCall( this.executeConditionalOrder, conditionalOrderId - ), + ), moduleData: moduleData, feeToken: ETH }); From c08a62a1cede20d7a3daa4df1ea3cb254ff16657 Mon Sep 17 00:00:00 2001 From: Flocqst Date: Mon, 20 May 2024 17:57:34 +0200 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9C=85=20Update=20orderflowfee=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/integration/orderFlowFee.behavior.t.sol | 34 ++++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/test/integration/orderFlowFee.behavior.t.sol b/test/integration/orderFlowFee.behavior.t.sol index 8168d53d..283e8c94 100644 --- a/test/integration/orderFlowFee.behavior.t.sol +++ b/test/integration/orderFlowFee.behavior.t.sol @@ -19,6 +19,8 @@ import {IPerpsV2MarketConsolidated} from "src/interfaces/IAccount.sol"; import {IPerpsV2ExchangeRate} from "src/interfaces/synthetix/IPerpsV2ExchangeRate.sol"; +import "forge-std/console2.sol"; + import { ADDRESS_RESOLVER, AMOUNT, @@ -139,7 +141,7 @@ contract OrderFlowFeeTest is Test, ConsolidatedEvents { /// Keep account margin to cover for orderFlowFee int256 marginDelta = int256(AMOUNT) / 5; - int256 sizeDelta = 1; + int256 sizeDelta = 1 ether; (uint256 desiredFillPrice,) = IPerpsV2MarketConsolidated(market).assetPrice(); @@ -152,8 +154,9 @@ contract OrderFlowFeeTest is Test, ConsolidatedEvents { if (fee == 0) { assertEq(imposedOrderFlowFee, 0); } else { - uint256 orderFlowFeeMath = abs(sizeDelta) * sUSDmarketRate - * settings.orderFlowFee() / settings.MAX_ORDER_FLOW_FEE(); + // Size is 1 ETH, so fee should be the orderflowfee value of 1 ETH in sUSD + uint256 orderFlowFeeMath = sUSDmarketRate * settings.orderFlowFee() + / settings.MAX_ORDER_FLOW_FEE(); assertEq(orderFlowFeeMath, imposedOrderFlowFee); } } @@ -297,9 +300,10 @@ contract OrderFlowFeeTest is Test, ConsolidatedEvents { // create a long position in the ETH market address market = getMarketAddressFromKey(sETHPERP); - /// Leave 10_000 in account (not enough to cover fees) - int256 marginDelta = int256(AMOUNT) - 10_000; - int256 sizeDelta = 1; + /// orderFlowFee is 94025250000000000 in the following configuration + /// Leave 50000000000 in account (not enough to cover fees) + int256 marginDelta = int256(AMOUNT) - 50_000_000_000; + int256 sizeDelta = 1 ether; (uint256 desiredFillPrice,) = IPerpsV2MarketConsolidated(market).assetPrice(); @@ -312,15 +316,17 @@ contract OrderFlowFeeTest is Test, ConsolidatedEvents { account.getPosition(sETHPERP); (, uint256 imposedOrderFlowFee) = - account.getExpectedOrderFlowFee(market, position.size); + account.getExpectedOrderFlowFee(market, sizeDelta); // Account margin is emptied assertEq(account.freeMargin(), 0); - // Market margin is reduced by (imposedOrderFlowFee - 10 000) + // Market margin is reduced by the missing amount to cover fee + // uint256(marginDelta) - 563537402924844194061 is the effective position margin when there is no orderflowfee assertEq( uint256(position.margin), - uint256(marginDelta) - (imposedOrderFlowFee - 10_000) - 563 + uint256(marginDelta) - 563_537_402_924_844_194_061 + - imposedOrderFlowFee + 50_000_000_000 ); // Assert that fee was correctly sent to treasury address @@ -331,10 +337,10 @@ contract OrderFlowFeeTest is Test, ConsolidatedEvents { /// @dev Synthetix makes transaction reverts if the resulting position is too large, outside the max leverage, or is liquidating. function test_imposeOrderFlowFee_market_margin_failed() public { // Set orderflow fee high to easily test that transaction fails if neither account or market has sufficient margin to cover for fees - uint256 testOrderFlowFee = 10_000; // 10% + uint256 testOrderFlowFee = 50_000; // 50% settings.setOrderFlowFee(testOrderFlowFee); - fundAccount(1000 ether); + fundAccount(AMOUNT); uint256 treasuryPreBalance = sUSD.balanceOf(settings.TREASURY()); @@ -342,8 +348,8 @@ contract OrderFlowFeeTest is Test, ConsolidatedEvents { address market = getMarketAddressFromKey(sETHPERP); /// Deposit all available account margin into market margin - int256 marginDelta = int256(1000 ether); - int256 sizeDelta = 1 ether; + int256 marginDelta = int256(AMOUNT); + int256 sizeDelta = 10 ether; (uint256 desiredFillPrice,) = IPerpsV2MarketConsolidated(market).assetPrice(); @@ -381,7 +387,7 @@ contract OrderFlowFeeTest is Test, ConsolidatedEvents { /// Keep account margin to cover for orderFlowFee int256 marginDelta = int256(AMOUNT) / 5; - int256 sizeDelta = 1; + int256 sizeDelta = 1 ether; (uint256 desiredFillPrice,) = IPerpsV2MarketConsolidated(market).assetPrice();