From ed767bfb97528f63a8a89b0a7f781034ba34e220 Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Mon, 11 Dec 2023 13:12:18 -0700 Subject: [PATCH 01/18] =?UTF-8?q?=F0=9F=91=B7=F0=9F=8F=BB=E2=80=8D?= =?UTF-8?q?=E2=99=82=EF=B8=8F=20Update=20co=20price=20condition=20checks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Engine.sol | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/Engine.sol b/src/Engine.sol index 3793abae..fcd9597b 100644 --- a/src/Engine.sol +++ b/src/Engine.sol @@ -663,30 +663,28 @@ contract Engine is IEngine, EIP712, EIP7412, ERC2771Context { /// @inheritdoc IEngine function isPriceAbove( - bytes32 _assetId, - int64 _price, - uint64 _confidenceInterval + uint128 _assetId, + uint128 _price ) public view override returns (bool) { - PythStructs.Price memory priceData = ORACLE.getPrice(_assetId); + (, uint256 fillPrice) = PERPS_MARKET_PROXY.computeOrderFees({ + marketId: _getMarketId(_assetId), + sizeDelta: 0 + }); - /// @dev although counterintuitive, a smaller confidence interval is more accurate. - /// The Engine must ensure the current confidence interval is not - /// greater (i.e. less accurate) than the confidence interval defined by the condition. - return priceData.price > _price && priceData.conf <= _confidenceInterval; + return fillPrice > _price; } /// @inheritdoc IEngine function isPriceBelow( - bytes32 _assetId, - int64 _price, - uint64 _confidenceInterval + uint128 _assetId, + uint128 _price ) public view override returns (bool) { - PythStructs.Price memory priceData = ORACLE.getPrice(_assetId); + (, uint256 fillPrice) = PERPS_MARKET_PROXY.computeOrderFees({ + marketId: _getMarketId(_assetId), + sizeDelta: 0 + }); - /// @dev although counterintuitive, a smaller confidence interval is more accurate. - /// The Engine must ensure the current confidence interval is not - /// greater (i.e. less accurate) than the confidence interval defined by the condition. - return priceData.price < _price && priceData.conf <= _confidenceInterval; + return priceData.price < _price; } /// @inheritdoc IEngine From 340353ad88dc4d02ceb44a370c51566dd3fc8603 Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Mon, 11 Dec 2023 13:12:47 -0700 Subject: [PATCH 02/18] =?UTF-8?q?=F0=9F=91=B7=F0=9F=8F=BB=E2=80=8D?= =?UTF-8?q?=E2=99=82=EF=B8=8F=20Update=20engine=20interface=20to=20reflect?= =?UTF-8?q?=20logic=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/interfaces/IEngine.sol | 40 ++++++-------------------------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/src/interfaces/IEngine.sol b/src/interfaces/IEngine.sol index b2fed3e4..5d21edfb 100644 --- a/src/interfaces/IEngine.sol +++ b/src/interfaces/IEngine.sol @@ -381,51 +381,23 @@ interface IEngine { returns (bool); /// @notice determine if the current price of an asset is above a given price - /// @dev assets price is determined by the pyth oracle + /// @dev relies on Synthetix Perps v3 market's simulated fill price /// @param _assetId id of an asset to check the price of /// @param _price the price to compare against - /// @param _confidenceInterval roughly corresponds to the standard error of a normal distribution - /// - /// example: - /// given: - /// PythStructs.Price.expo (expo) = -5 - /// confidenceInterval (conf) = 1500 - /// PythStructs.Price.price (price) = 12276250 - /// - /// conf * 10^(expo) = 1500 * 10^(-5) = $0.015 - /// price * 10^(-5) = 12276250 * 10^(-5) = $122.7625 - /// - /// thus, the price of the asset is $122.7625 +/- $0.015 - /// /// @return true if the current price of the asset is above the given `_price`, false otherwise function isPriceAbove( - bytes32 _assetId, - int64 _price, - uint64 _confidenceInterval + uint128 _assetId, + uint128 _price ) external view returns (bool); /// @notice determine if the current price of an asset is below a given price - /// @dev assets price is determined by the pyth oracle + /// @dev relies on Synthetix Perps v3 market's simulated fill price /// @param _assetId id of an asset to check the price of /// @param _price the price to compare against - /// @param _confidenceInterval roughly corresponds to the standard error of a normal distribution - /// - /// example: - /// given: - /// PythStructs.Price.expo (expo) = -5 - /// confidenceInterval (conf) = 1500 - /// PythStructs.Price.price (price) = 12276250 - /// - /// conf * 10^(expo) = 1500 * 10^(-5) = $0.015 - /// price * 10^(-5) = 12276250 * 10^(-5) = $122.7625 - /// - /// thus, the price of the asset is $122.7625 +/- $0.015 - /// /// @return true if the current price of the asset is below the given `_price`, false otherwise function isPriceBelow( - bytes32 _assetId, - int64 _price, - uint64 _confidenceInterval + uint128 _assetId, + uint128 _price ) external view returns (bool); /// @notice can market accept non close-only orders (i.e. is the market open) From 4c6a5253e8ddea49d4d0286eb9b9bc3f4e66f611 Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:32:00 -0500 Subject: [PATCH 03/18] =?UTF-8?q?=F0=9F=93=9A=20Update=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index dcd7cbd8..099d6436 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,6 @@ src/ ├── Engine.sol ├── interfaces │ ├── IEngine.sol -│ ├── oracles -│ │ └── IPyth.sol │ ├── synthetix │ │ ├── IERC7412.sol │ │ ├── IPerpsMarketProxy.sol @@ -81,7 +79,7 @@ npm run decode-custom-error -- > project must be compiled first (see step 2) ``` -npx hardhat test +npm run test:hh ``` ## Deployment Addresses From b06eda0ad0abc9d22b6526f4e045ddfe309b078c Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:32:35 -0500 Subject: [PATCH 04/18] =?UTF-8?q?=F0=9F=91=B7=F0=9F=8F=BB=E2=80=8D?= =?UTF-8?q?=E2=99=82=EF=B8=8F=20Update=20co=20price=20condition=20checks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Engine.sol | 36 +++++++-------- src/interfaces/IEngine.sol | 30 ++++++------ src/interfaces/oracles/IPyth.sol | 78 -------------------------------- 3 files changed, 32 insertions(+), 112 deletions(-) delete mode 100644 src/interfaces/oracles/IPyth.sol diff --git a/src/Engine.sol b/src/Engine.sol index fcd9597b..bd16a20f 100644 --- a/src/Engine.sol +++ b/src/Engine.sol @@ -7,7 +7,6 @@ import {EIP712} from "src/utils/EIP712.sol"; import {EIP7412} from "src/utils/EIP7412.sol"; import {IEngine, IPerpsMarketProxy} from "src/interfaces/IEngine.sol"; import {IERC20} from "src/interfaces/tokens/IERC20.sol"; -import {IPyth, PythStructs} from "src/interfaces/oracles/IPyth.sol"; import {ISpotMarketProxy} from "src/interfaces/synthetix/ISpotMarketProxy.sol"; import {MathLib} from "src/libraries/MathLib.sol"; import {SignatureCheckerLib} from "src/libraries/SignatureCheckerLib.sol"; @@ -62,9 +61,6 @@ contract Engine is IEngine, EIP712, EIP7412, ERC2771Context { IMMUTABLES //////////////////////////////////////////////////////////////*/ - /// @notice pyth oracle contract used to get asset prices - IPyth internal immutable ORACLE; - /// @notice Synthetix v3 perps market proxy contract IPerpsMarketProxy internal immutable PERPS_MARKET_PROXY; @@ -97,22 +93,18 @@ contract Engine is IEngine, EIP712, EIP7412, ERC2771Context { /// @param _perpsMarketProxy Synthetix v3 perps market proxy contract /// @param _spotMarketProxy Synthetix v3 spot market proxy contract /// @param _sUSDProxy Synthetix v3 sUSD contract - /// @param _oracle pyth oracle contract used to get asset prices constructor( address _perpsMarketProxy, address _spotMarketProxy, - address _sUSDProxy, - address _oracle + address _sUSDProxy ) ERC2771Context(address(new TrustedForwarder())) { if (_perpsMarketProxy == address(0)) revert ZeroAddress(); if (_spotMarketProxy == address(0)) revert ZeroAddress(); if (_sUSDProxy == address(0)) revert ZeroAddress(); - if (_oracle == address(0)) revert ZeroAddress(); PERPS_MARKET_PROXY = IPerpsMarketProxy(_perpsMarketProxy); SPOT_MARKET_PROXY = ISpotMarketProxy(_spotMarketProxy); SUSD = IERC20(_sUSDProxy); - ORACLE = IPyth(_oracle); } /*////////////////////////////////////////////////////////////// @@ -662,12 +654,14 @@ contract Engine is IEngine, EIP712, EIP7412, ERC2771Context { } /// @inheritdoc IEngine - function isPriceAbove( - uint128 _assetId, - uint128 _price - ) public view override returns (bool) { + function isPriceAbove(uint128 _marketId, uint256 _price) + public + view + override + returns (bool) + { (, uint256 fillPrice) = PERPS_MARKET_PROXY.computeOrderFees({ - marketId: _getMarketId(_assetId), + marketId: _marketId, sizeDelta: 0 }); @@ -675,16 +669,18 @@ contract Engine is IEngine, EIP712, EIP7412, ERC2771Context { } /// @inheritdoc IEngine - function isPriceBelow( - uint128 _assetId, - uint128 _price - ) public view override returns (bool) { + function isPriceBelow(uint128 _marketId, uint256 _price) + public + view + override + returns (bool) + { (, uint256 fillPrice) = PERPS_MARKET_PROXY.computeOrderFees({ - marketId: _getMarketId(_assetId), + marketId: _marketId, sizeDelta: 0 }); - return priceData.price < _price; + return fillPrice < _price; } /// @inheritdoc IEngine diff --git a/src/interfaces/IEngine.sol b/src/interfaces/IEngine.sol index 5d21edfb..36ebbd46 100644 --- a/src/interfaces/IEngine.sol +++ b/src/interfaces/IEngine.sol @@ -380,25 +380,27 @@ interface IEngine { view returns (bool); - /// @notice determine if the current price of an asset is above a given price + /// @notice determine if the simulated fill price is above a given price /// @dev relies on Synthetix Perps v3 market's simulated fill price - /// @param _assetId id of an asset to check the price of + /// @param _marketId id a market used to check the price of the + /// underlying asset of that market (i.e. ETH Perp Market -> ETH) /// @param _price the price to compare against - /// @return true if the current price of the asset is above the given `_price`, false otherwise - function isPriceAbove( - uint128 _assetId, - uint128 _price - ) external view returns (bool); + /// @return true if the simulated fill price is above the given `_price`, false otherwise + function isPriceAbove(uint128 _marketId, uint256 _price) + external + view + returns (bool); - /// @notice determine if the current price of an asset is below a given price + /// @notice determine if the simulated fill price is below a given price /// @dev relies on Synthetix Perps v3 market's simulated fill price - /// @param _assetId id of an asset to check the price of + /// @param _marketId id a market used to check the price of the + /// underlying asset of that market (i.e. ETH Perp Market -> ETH) /// @param _price the price to compare against - /// @return true if the current price of the asset is below the given `_price`, false otherwise - function isPriceBelow( - uint128 _assetId, - uint128 _price - ) external view returns (bool); + /// @return true if the simulated fill price is below the given `_price`, false otherwise + function isPriceBelow(uint128 _marketId, uint256 _price) + external + view + returns (bool); /// @notice can market accept non close-only orders (i.e. is the market open) /// @dev if maxMarketSize to 0, the market will be in a close-only state diff --git a/src/interfaces/oracles/IPyth.sol b/src/interfaces/oracles/IPyth.sol deleted file mode 100644 index 6d514efc..00000000 --- a/src/interfaces/oracles/IPyth.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.20; - -/// @title Consume prices from the Pyth Network (https://pyth.network/). -/// @dev Please refer to the guidance at https://docs.pyth.network/consumers/best-practices for how to consume prices safely. -/// @author Pyth Data Association -interface IPyth { - /// @dev Emitted when an update for price feed with `id` is processed successfully. - /// @param id The Pyth Price Feed ID. - /// @param fresh True if the price update is more recent and stored. - /// @param chainId ID of the source chain that the batch price update containing this price. - /// This value comes from Wormhole, and you can find the corresponding chains at https://docs.wormholenetwork.com/wormhole/contracts. - /// @param sequenceNumber Sequence number of the batch price update containing this price. - /// @param lastPublishTime Publish time of the previously stored price. - /// @param publishTime Publish time of the given price update. - /// @param price Price of the given price update. - /// @param conf Confidence interval of the given price update. - event PriceFeedUpdate( - bytes32 indexed id, - bool indexed fresh, - uint16 chainId, - uint64 sequenceNumber, - uint256 lastPublishTime, - uint256 publishTime, - int64 price, - uint64 conf - ); - - /// @dev Emitted when a batch price update is processed successfully. - /// @param chainId ID of the source chain that the batch price update comes from. - /// @param sequenceNumber Sequence number of the batch price update. - /// @param batchSize Number of prices within the batch price update. - /// @param freshPricesInBatch Number of prices that were more recent and were stored. - event BatchPriceFeedUpdate( - uint16 chainId, - uint64 sequenceNumber, - uint256 batchSize, - uint256 freshPricesInBatch - ); - - /// @dev Emitted when a call to `updatePriceFeeds` is processed successfully. - /// @param sender Sender of the call (`msg.sender`). - /// @param batchCount Number of batches that this function processed. - /// @param fee Amount of paid fee for updating the prices. - event UpdatePriceFeeds( - address indexed sender, uint256 batchCount, uint256 fee - ); - - /// @notice Returns the price and confidence interval. - /// @dev Reverts if the price has not been updated within the last `getValidTimePeriod()` seconds. - /// @param id The Pyth Price Feed ID of which to fetch the price and confidence interval. - /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. - function getPrice(bytes32 id) - external - view - returns (PythStructs.Price memory price); -} - -contract PythStructs { - // A price with a degree of uncertainty, represented as a price +- a confidence interval. - // - // The confidence interval roughly corresponds to the standard error of a normal distribution. - // Both the price and confidence are stored in a fixed-point numeric representation, - // `x * (10^expo)`, where `expo` is the exponent. - // - // Please refer to the documentation at https://docs.pyth.network/consumers/best-practices for how - // to how this price safely. - struct Price { - // Price - int64 price; - // Confidence interval around the price - uint64 conf; - // Price exponent - int32 expo; - // Unix timestamp describing when the price was published - uint256 publishTime; - } -} From 83879bfe97e573ed78698ed0dcecdd148645ffa9 Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:33:08 -0500 Subject: [PATCH 05/18] =?UTF-8?q?=F0=9F=9A=80=20Update=20deployment=20scri?= =?UTF-8?q?pts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/Deploy.s.sol | 24 +++++++------------ .../BaseGoerliKwentaForkParameters.sol | 2 -- .../utils/parameters/BaseGoerliParameters.sol | 2 -- script/utils/parameters/BaseParameters.sol | 2 -- .../parameters/OptimismGoerliParameters.sol | 2 -- .../utils/parameters/OptimismParameters.sol | 2 -- 6 files changed, 8 insertions(+), 26 deletions(-) diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index cabfd78f..1fd45b24 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -24,14 +24,12 @@ contract Setup is Script { function deploySystem( address perpsMarketProxy, address spotMarketProxy, - address sUSDProxy, - address oracle + address sUSDProxy ) public returns (Engine engine) { engine = new Engine({ _perpsMarketProxy: perpsMarketProxy, _spotMarketProxy: spotMarketProxy, - _sUSDProxy: sUSDProxy, - _oracle: oracle + _sUSDProxy: sUSDProxy }); } } @@ -47,8 +45,7 @@ contract DeployBase_Synthetix is Setup, BaseParameters { Setup.deploySystem({ perpsMarketProxy: PERPS_MARKET_PROXY, spotMarketProxy: SPOT_MARKET_PROXY, - sUSDProxy: USD_PROXY, - oracle: PYTH + sUSDProxy: USD_PROXY }); vm.stopBroadcast(); @@ -66,8 +63,7 @@ contract DeployBaseGoerli_Synthetix is Setup, BaseGoerliParameters { Setup.deploySystem({ perpsMarketProxy: PERPS_MARKET_PROXY, spotMarketProxy: SPOT_MARKET_PROXY, - sUSDProxy: USD_PROXY, - oracle: PYTH + sUSDProxy: USD_PROXY }); vm.stopBroadcast(); @@ -88,8 +84,7 @@ contract DeployBaseGoerli_KwentaFork is Setup.deploySystem({ perpsMarketProxy: PERPS_MARKET_PROXY, spotMarketProxy: SPOT_MARKET_PROXY, - sUSDProxy: USD_PROXY, - oracle: PYTH + sUSDProxy: USD_PROXY }); vm.stopBroadcast(); @@ -107,8 +102,7 @@ contract DeployBaseGoerli_Andromeda is Setup, BaseGoerliParameters { Setup.deploySystem({ perpsMarketProxy: PERPS_MARKET_PROXY_ANDROMEDA, spotMarketProxy: SPOT_MARKET_PROXY_ANDROMEDA, - sUSDProxy: USD_PROXY_ANDROMEDA, - oracle: PYTH + sUSDProxy: USD_PROXY_ANDROMEDA }); vm.stopBroadcast(); @@ -126,8 +120,7 @@ contract DeployOptimism_Synthetix is Setup, OptimismParameters { Setup.deploySystem({ perpsMarketProxy: PERPS_MARKET_PROXY, spotMarketProxy: SPOT_MARKET_PROXY, - sUSDProxy: USD_PROXY, - oracle: PYTH + sUSDProxy: USD_PROXY }); vm.stopBroadcast(); @@ -145,8 +138,7 @@ contract DeployOptimismGoerli_Synthetix is Setup, OptimismGoerliParameters { Setup.deploySystem({ perpsMarketProxy: PERPS_MARKET_PROXY, spotMarketProxy: SPOT_MARKET_PROXY, - sUSDProxy: USD_PROXY, - oracle: PYTH + sUSDProxy: USD_PROXY }); vm.stopBroadcast(); diff --git a/script/utils/parameters/BaseGoerliKwentaForkParameters.sol b/script/utils/parameters/BaseGoerliKwentaForkParameters.sol index fc106902..f50cdf9d 100644 --- a/script/utils/parameters/BaseGoerliKwentaForkParameters.sol +++ b/script/utils/parameters/BaseGoerliKwentaForkParameters.sol @@ -10,6 +10,4 @@ contract BaseGoerliKwentaForkParameters { address public constant USD_PROXY = 0xD3bcDae94B0c2EF16d1c43d29c23b1735d864fC6; - - address public constant PYTH = 0x5955C1478F0dAD753C7E2B4dD1b4bC530C64749f; } diff --git a/script/utils/parameters/BaseGoerliParameters.sol b/script/utils/parameters/BaseGoerliParameters.sol index d1da4175..88325dc3 100644 --- a/script/utils/parameters/BaseGoerliParameters.sol +++ b/script/utils/parameters/BaseGoerliParameters.sol @@ -11,8 +11,6 @@ contract BaseGoerliParameters { address public constant USD_PROXY = 0x579c612E4Bf390f5504DB9f76b6F5759A3172279; - address public constant PYTH = 0x5955C1478F0dAD753C7E2B4dD1b4bC530C64749f; - // https://usecannon.com/packages/synthetix-omnibus/latest/84531-andromeda address public constant PERPS_MARKET_PROXY_ANDROMEDA = 0x75c43165ea38cB857C45216a37C5405A7656673c; diff --git a/script/utils/parameters/BaseParameters.sol b/script/utils/parameters/BaseParameters.sol index 43d470c9..88d50a6f 100644 --- a/script/utils/parameters/BaseParameters.sol +++ b/script/utils/parameters/BaseParameters.sol @@ -7,6 +7,4 @@ contract BaseParameters { address public constant SPOT_MARKET_PROXY = address(0); address public constant USD_PROXY = address(0); - - address public constant PYTH = 0x8250f4aF4B972684F7b336503E2D6dFeDeB1487a; } diff --git a/script/utils/parameters/OptimismGoerliParameters.sol b/script/utils/parameters/OptimismGoerliParameters.sol index b3f2c52b..065ea18a 100644 --- a/script/utils/parameters/OptimismGoerliParameters.sol +++ b/script/utils/parameters/OptimismGoerliParameters.sol @@ -10,6 +10,4 @@ contract OptimismGoerliParameters { address public constant USD_PROXY = 0xe487Ad4291019b33e2230F8E2FB1fb6490325260; - - address public constant PYTH = 0xff1a0f4744e8582DF1aE09D5611b887B6a12925C; } diff --git a/script/utils/parameters/OptimismParameters.sol b/script/utils/parameters/OptimismParameters.sol index 05670010..4ea216fe 100644 --- a/script/utils/parameters/OptimismParameters.sol +++ b/script/utils/parameters/OptimismParameters.sol @@ -9,6 +9,4 @@ contract OptimismParameters { address public constant USD_PROXY = 0xb2F30A7C980f052f02563fb518dcc39e6bf38175; - - address public constant PYTH = 0xff1a0f4744e8582DF1aE09D5611b887B6a12925C; } From 15f8bdc1895331fa935ddd83f17bb7ecc6976b3b Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:33:48 -0500 Subject: [PATCH 06/18] =?UTF-8?q?=E2=9C=85=20Update=20Bootstrap=20&=20cons?= =?UTF-8?q?tants?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/utils/Bootstrap.sol | 32 ++++++++++---------------------- test/utils/Constants.sol | 3 --- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/test/utils/Bootstrap.sol b/test/utils/Bootstrap.sol index 9c194d4d..d23bf921 100644 --- a/test/utils/Bootstrap.sol +++ b/test/utils/Bootstrap.sol @@ -16,7 +16,6 @@ import { import {IERC20} from "src/interfaces/tokens/IERC20.sol"; import {IPerpsMarketProxy} from "test/utils/interfaces/IPerpsMarketProxy.sol"; import {ISpotMarketProxy} from "src/interfaces/synthetix/ISpotMarketProxy.sol"; -import {IPyth} from "src/interfaces/oracles/IPyth.sol"; import {SynthMinter} from "test/utils/SynthMinter.sol"; contract Bootstrap is Test, Constants, Conditions, SynthetixV3Errors { @@ -28,7 +27,6 @@ contract Bootstrap is Test, Constants, Conditions, SynthetixV3Errors { ISpotMarketProxy public spotMarketProxy; IERC20 public sUSD; IERC20 public sBTC; - IPyth public pyth; SynthMinter public synthMinter; uint128 public accountId; @@ -42,8 +40,7 @@ contract Bootstrap is Test, Constants, Conditions, SynthetixV3Errors { address _engineExposedAddress, address _perpesMarketProxyAddress, address _spotMarketProxyAddress, - address _sUSDAddress, - address _pythAddress + address _sUSDAddress ) = bootstrap.init(); engine = Engine(_engineAddress); @@ -51,7 +48,6 @@ contract Bootstrap is Test, Constants, Conditions, SynthetixV3Errors { perpsMarketProxy = IPerpsMarketProxy(_perpesMarketProxyAddress); spotMarketProxy = ISpotMarketProxy(_spotMarketProxyAddress); sUSD = IERC20(_sUSDAddress); - pyth = IPyth(_pythAddress); synthMinter = new SynthMinter(_sUSDAddress, _spotMarketProxyAddress); sBTC = synthMinter.sBTC(); @@ -74,8 +70,7 @@ contract Bootstrap is Test, Constants, Conditions, SynthetixV3Errors { address _engineExposedAddress, address _perpesMarketProxyAddress, address _spotMarketProxyAddress, - address _sUSDAddress, - address _pythAddress + address _sUSDAddress ) = bootstrap.init(); engine = Engine(_engineAddress); @@ -83,7 +78,6 @@ contract Bootstrap is Test, Constants, Conditions, SynthetixV3Errors { perpsMarketProxy = IPerpsMarketProxy(_perpesMarketProxyAddress); spotMarketProxy = ISpotMarketProxy(_spotMarketProxyAddress); sUSD = IERC20(_sUSDAddress); - pyth = IPyth(_pythAddress); synthMinter = new SynthMinter(_sUSDAddress, _spotMarketProxyAddress); sBTC = synthMinter.sBTC(); @@ -103,20 +97,18 @@ contract Bootstrap is Test, Constants, Conditions, SynthetixV3Errors { contract BootstrapOptimism is Setup, OptimismParameters { function init() public - returns (address, address, address, address, address, address) + returns (address, address, address, address, address) { (Engine engine) = Setup.deploySystem({ perpsMarketProxy: PERPS_MARKET_PROXY, spotMarketProxy: SPOT_MARKET_PROXY, - sUSDProxy: USD_PROXY, - oracle: PYTH + sUSDProxy: USD_PROXY }); EngineExposed engineExposed = new EngineExposed({ _perpsMarketProxy: PERPS_MARKET_PROXY, _spotMarketProxy: SPOT_MARKET_PROXY, - _sUSDProxy: USD_PROXY, - _oracle: PYTH + _sUSDProxy: USD_PROXY }); return ( @@ -124,8 +116,7 @@ contract BootstrapOptimism is Setup, OptimismParameters { address(engineExposed), PERPS_MARKET_PROXY, SPOT_MARKET_PROXY, - USD_PROXY, - PYTH + USD_PROXY ); } } @@ -133,20 +124,18 @@ contract BootstrapOptimism is Setup, OptimismParameters { contract BootstrapOptimismGoerli is Setup, OptimismGoerliParameters { function init() public - returns (address, address, address, address, address, address) + returns (address, address, address, address, address) { (Engine engine) = Setup.deploySystem({ perpsMarketProxy: PERPS_MARKET_PROXY, spotMarketProxy: SPOT_MARKET_PROXY, - sUSDProxy: USD_PROXY, - oracle: PYTH + sUSDProxy: USD_PROXY }); EngineExposed engineExposed = new EngineExposed({ _perpsMarketProxy: PERPS_MARKET_PROXY, _spotMarketProxy: SPOT_MARKET_PROXY, - _sUSDProxy: USD_PROXY, - _oracle: PYTH + _sUSDProxy: USD_PROXY }); return ( @@ -154,8 +143,7 @@ contract BootstrapOptimismGoerli is Setup, OptimismGoerliParameters { address(engineExposed), PERPS_MARKET_PROXY, SPOT_MARKET_PROXY, - USD_PROXY, - PYTH + USD_PROXY ); } } diff --git a/test/utils/Constants.sol b/test/utils/Constants.sol index 6bb534fa..752bc158 100644 --- a/test/utils/Constants.sol +++ b/test/utils/Constants.sol @@ -52,9 +52,6 @@ contract Constants { uint128 constant SETH_PERPS_MARKET_ID = 200; - bytes32 constant PYTH_ETH_USD_ASSET_ID = - 0xca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a6; - uint256 internal constant AMOUNT = 10_000 ether; address internal constant MARKET_CONFIGURATION_MODULE = From a17797a42da2ff75919b0f4e9969299f19d6d735 Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:34:12 -0500 Subject: [PATCH 07/18] =?UTF-8?q?=E2=9C=85=20Update=20Mocks,=20Utils,=20et?= =?UTF-8?q?c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/utils/Conditions.sol | 24 ++++++++++++------------ test/utils/exposed/EngineExposed.sol | 5 ++--- test/utils/mocks/PythMock.sol | 21 --------------------- test/utils/mocks/SynthetixMock.sol | 16 ---------------- 4 files changed, 14 insertions(+), 52 deletions(-) delete mode 100644 test/utils/mocks/PythMock.sol diff --git a/test/utils/Conditions.sol b/test/utils/Conditions.sol index 52e56dbb..299f37bf 100644 --- a/test/utils/Conditions.sol +++ b/test/utils/Conditions.sol @@ -22,23 +22,23 @@ contract Conditions { abi.encodeWithSelector(Engine.isTimestampBefore.selector, timestamp); } - function isPriceAbove( - bytes32 _assetId, - int64 _price, - uint64 _confidenceInterval - ) public pure returns (bytes memory) { + function isPriceAbove(uint128 _marketId, uint256 _price) + public + pure + returns (bytes memory) + { return abi.encodeWithSelector( - Engine.isPriceAbove.selector, _assetId, _price, _confidenceInterval + Engine.isPriceAbove.selector, _marketId, _price ); } - function isPriceBelow( - bytes32 _assetId, - int64 _price, - uint64 _confidenceInterval - ) public pure returns (bytes memory) { + function isPriceBelow(uint128 _marketId, uint256 _price) + public + pure + returns (bytes memory) + { return abi.encodeWithSelector( - Engine.isPriceBelow.selector, _assetId, _price, _confidenceInterval + Engine.isPriceBelow.selector, _marketId, _price ); } diff --git a/test/utils/exposed/EngineExposed.sol b/test/utils/exposed/EngineExposed.sol index 34b04565..35b9b1fc 100644 --- a/test/utils/exposed/EngineExposed.sol +++ b/test/utils/exposed/EngineExposed.sol @@ -9,9 +9,8 @@ contract EngineExposed is Engine { constructor( address _perpsMarketProxy, address _spotMarketProxy, - address _sUSDProxy, - address _oracle - ) Engine(_perpsMarketProxy, _spotMarketProxy, _sUSDProxy, _oracle) {} + address _sUSDProxy + ) Engine(_perpsMarketProxy, _spotMarketProxy, _sUSDProxy) {} function getSynthAddress(uint128 synthMarketId) public diff --git a/test/utils/mocks/PythMock.sol b/test/utils/mocks/PythMock.sol deleted file mode 100644 index 1bf8b8cd..00000000 --- a/test/utils/mocks/PythMock.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.20; - -import {IPyth} from "src/interfaces/oracles/IPyth.sol"; -import {Test} from "lib/forge-std/src/Test.sol"; - -contract PythMock is Test { - function mock_pyth_getPrice( - address pyth, - bytes32 id, - int64 price, - uint64 conf, - int32 expo - ) public { - vm.mockCall( - pyth, - abi.encodeWithSelector(IPyth.getPrice.selector, id), - abi.encode(price, conf, expo, block.timestamp - 1) - ); - } -} diff --git a/test/utils/mocks/SynthetixMock.sol b/test/utils/mocks/SynthetixMock.sol index 5470ddf4..88395822 100644 --- a/test/utils/mocks/SynthetixMock.sol +++ b/test/utils/mocks/SynthetixMock.sol @@ -5,22 +5,6 @@ import {IPerpsMarketProxy} from "test/utils/interfaces/IPerpsMarketProxy.sol"; import {Test} from "lib/forge-std/src/Test.sol"; contract SynthetixMock is Test { - function mock_computeOrderFees( - address perpsMarketProxy, - uint128 marketId, - int128 sizeDelta, - uint256 orderFees, - uint256 fillPrice - ) public { - vm.mockCall( - perpsMarketProxy, - abi.encodeWithSelector( - IPerpsMarketProxy.computeOrderFees.selector, marketId, sizeDelta - ), - abi.encode(orderFees, fillPrice) - ); - } - function mock_getOpenPosition( address perpsMarketProxy, uint128 accountId, From 4393ea042660f8e8ab842fe2af3b622e79284e8f Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:34:27 -0500 Subject: [PATCH 08/18] =?UTF-8?q?=E2=9C=85=20Update=20forge=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/ConditionalOrder.t.sol | 101 +++++++++--------------------------- test/Deployment.t.sol | 23 ++------ 2 files changed, 29 insertions(+), 95 deletions(-) diff --git a/test/ConditionalOrder.t.sol b/test/ConditionalOrder.t.sol index 3571257c..811afad3 100644 --- a/test/ConditionalOrder.t.sol +++ b/test/ConditionalOrder.t.sol @@ -6,13 +6,11 @@ import {ConditionalOrderSignature} from "test/utils/ConditionalOrderSignature.sol"; import {IEngine} from "src/interfaces/IEngine.sol"; import {IPerpsMarketProxy} from "src/interfaces/synthetix/IPerpsMarketProxy.sol"; -import {PythMock} from "test/utils/mocks/PythMock.sol"; import {SynthetixMock} from "test/utils/mocks/SynthetixMock.sol"; contract ConditionalOrderTest is Bootstrap, ConditionalOrderSignature, - PythMock, SynthetixMock { address signer; @@ -325,16 +323,6 @@ contract VerifyConditions is ConditionalOrderTest { } function test_verify_conditions_verified() public { - int64 mock_price = 173_078_000_000; - bytes32 mock_assetId = PYTH_ETH_USD_ASSET_ID; - mock_pyth_getPrice({ - pyth: address(pyth), - id: mock_assetId, - price: mock_price, - conf: 45_999_999, - expo: -8 - }); - mock_getOpenPosition({ perpsMarketProxy: address(perpsMarketProxy), accountId: accountId, @@ -345,10 +333,8 @@ contract VerifyConditions is ConditionalOrderTest { bytes[] memory conditions = new bytes[](8); conditions[0] = isTimestampAfter(0); conditions[1] = isTimestampBefore(type(uint256).max); - conditions[2] = isPriceAbove(PYTH_ETH_USD_ASSET_ID, 0, type(uint64).max); - conditions[3] = isPriceBelow( - PYTH_ETH_USD_ASSET_ID, type(int64).max, type(uint64).max - ); + conditions[2] = isPriceAbove(SETH_PERPS_MARKET_ID, 0); + conditions[3] = isPriceBelow(SETH_PERPS_MARKET_ID, type(uint256).max); conditions[4] = isMarketOpen(SETH_PERPS_MARKET_ID); conditions[5] = isPositionSizeAbove(accountId, SETH_PERPS_MARKET_ID, 0); conditions[6] = isPositionSizeBelow( @@ -375,21 +361,11 @@ contract VerifyConditions is ConditionalOrderTest { } function test_verify_conditions_not_verified() public { - int64 mock_price = 173_078_000_000; - bytes32 mock_assetId = PYTH_ETH_USD_ASSET_ID; - mock_pyth_getPrice({ - pyth: address(pyth), - id: mock_assetId, - price: mock_price, - conf: 45_999_999, - expo: -8 - }); - bytes[] memory conditions = new bytes[](5); conditions[0] = isTimestampAfter(0); conditions[1] = isTimestampBefore(type(uint256).max); - conditions[2] = isPriceAbove(PYTH_ETH_USD_ASSET_ID, 0, type(uint64).max); - conditions[3] = isPriceBelow(PYTH_ETH_USD_ASSET_ID, 0, type(uint64).max); // false + conditions[2] = isPriceAbove(SETH_PERPS_MARKET_ID, 0); + conditions[3] = isPriceBelow(SETH_PERPS_MARKET_ID, 0); // false; price not below 0 conditions[4] = isMarketOpen(SETH_PERPS_MARKET_ID); IEngine.OrderDetails memory orderDetails; @@ -1025,68 +1001,41 @@ contract Conditions is ConditionalOrderTest { } function test_isPriceAbove() public { - int64 mock_price = 173_078_000_000; - bytes32 mock_assetId = PYTH_ETH_USD_ASSET_ID; - uint64 mock_confidenceInterval = 45_999_999; - mock_pyth_getPrice({ - pyth: address(pyth), - id: mock_assetId, - price: 173_078_000_000, - conf: mock_confidenceInterval, - expo: -8 - }); - - bool isAbove = engine.isPriceAbove( - mock_assetId, mock_price - 1, mock_confidenceInterval - ); + (, uint256 currentFillPrice) = + perpsMarketProxy.computeOrderFees(SETH_PERPS_MARKET_ID, 0); + + bool isAbove = engine.isPriceAbove(SETH_PERPS_MARKET_ID, 0); assertTrue(isAbove); - isAbove = engine.isPriceAbove( - mock_assetId, mock_price, mock_confidenceInterval - ); + isAbove = engine.isPriceAbove(SETH_PERPS_MARKET_ID, currentFillPrice); assertFalse(isAbove); - isAbove = engine.isPriceAbove( - mock_assetId, mock_price + 1, mock_confidenceInterval - ); + isAbove = + engine.isPriceAbove(SETH_PERPS_MARKET_ID, currentFillPrice + 1); assertFalse(isAbove); - isAbove = engine.isPriceAbove( - mock_assetId, mock_price - 1, mock_confidenceInterval - 1 - ); - assertFalse(isAbove); + isAbove = isAbove = + engine.isPriceAbove(SETH_PERPS_MARKET_ID, currentFillPrice - 1); + assertTrue(isAbove); } function test_isPriceBelow() public { - int64 mock_price = 173_078_000_000; - bytes32 mock_assetId = PYTH_ETH_USD_ASSET_ID; - uint64 mock_confidenceInterval = 45_999_999; - mock_pyth_getPrice({ - pyth: address(pyth), - id: mock_assetId, - price: 173_078_000_000, - conf: mock_confidenceInterval, - expo: -8 - }); - - bool isBelow = engine.isPriceBelow( - mock_assetId, mock_price - 1, mock_confidenceInterval - ); - assertFalse(isBelow); + (, uint256 currentFillPrice) = + perpsMarketProxy.computeOrderFees(SETH_PERPS_MARKET_ID, 0); - isBelow = engine.isPriceBelow( - mock_assetId, mock_price, mock_confidenceInterval - ); + bool isBelow = + engine.isPriceBelow(SETH_PERPS_MARKET_ID, type(uint256).max); + assertTrue(isBelow); + + isBelow = engine.isPriceBelow(SETH_PERPS_MARKET_ID, currentFillPrice); assertFalse(isBelow); - isBelow = engine.isPriceBelow( - mock_assetId, mock_price + 1, mock_confidenceInterval - ); + isBelow = + engine.isPriceBelow(SETH_PERPS_MARKET_ID, currentFillPrice + 1); assertTrue(isBelow); - isBelow = engine.isPriceBelow( - mock_assetId, mock_price + 1, mock_confidenceInterval - 1 - ); + isBelow = isBelow = + engine.isPriceBelow(SETH_PERPS_MARKET_ID, currentFillPrice - 1); assertFalse(isBelow); } diff --git a/test/Deployment.t.sol b/test/Deployment.t.sol index 06a09d46..4ba22af5 100644 --- a/test/Deployment.t.sol +++ b/test/Deployment.t.sol @@ -16,8 +16,7 @@ contract DeploymentTest is Test, Setup { (Engine engine) = setup.deploySystem({ perpsMarketProxy: address(0x1), spotMarketProxy: address(0x2), - sUSDProxy: address(0x3), - oracle: address(0x4) + sUSDProxy: address(0x3) }); assertTrue(address(engine) != address(0x0)); @@ -27,8 +26,7 @@ contract DeploymentTest is Test, Setup { try setup.deploySystem({ perpsMarketProxy: address(0), spotMarketProxy: address(0x2), - sUSDProxy: address(0x3), - oracle: address(0x4) + sUSDProxy: address(0x3) }) {} catch (bytes memory reason) { assertEq(bytes4(reason), IEngine.ZeroAddress.selector); } @@ -38,8 +36,7 @@ contract DeploymentTest is Test, Setup { try setup.deploySystem({ perpsMarketProxy: address(0x1), spotMarketProxy: address(0), - sUSDProxy: address(0x3), - oracle: address(0x4) + sUSDProxy: address(0x3) }) {} catch (bytes memory reason) { assertEq(bytes4(reason), IEngine.ZeroAddress.selector); } @@ -49,19 +46,7 @@ contract DeploymentTest is Test, Setup { try setup.deploySystem({ perpsMarketProxy: address(0x1), spotMarketProxy: address(0x2), - sUSDProxy: address(0), - oracle: address(0x4) - }) {} catch (bytes memory reason) { - assertEq(bytes4(reason), IEngine.ZeroAddress.selector); - } - } - - function test_deploy_oracle_zero_address() public { - try setup.deploySystem({ - perpsMarketProxy: address(0x1), - spotMarketProxy: address(0x2), - sUSDProxy: address(0x3), - oracle: address(0) + sUSDProxy: address(0) }) {} catch (bytes memory reason) { assertEq(bytes4(reason), IEngine.ZeroAddress.selector); } From efbbb20164f4ebe4990502640d285cd00828966b Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:34:38 -0500 Subject: [PATCH 09/18] =?UTF-8?q?=E2=9C=85=20Update=20hardhat=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/Signature.test.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/Signature.test.ts b/test/Signature.test.ts index 6432d92f..f543518f 100644 --- a/test/Signature.test.ts +++ b/test/Signature.test.ts @@ -41,10 +41,9 @@ describe("Signature", function () { const Engine = await ethers.getContractFactory("Engine"); const engine = await Engine.deploy( - ONE_ADDRESS, - ONE_ADDRESS, - ONE_ADDRESS, - ONE_ADDRESS + ONE_ADDRESS, // Perps Market Proxy Address + ONE_ADDRESS, // Spot Market Proxy Address + ONE_ADDRESS // sUSD Token Proxy Address ); await engine.waitForDeployment(); From 890ca55fe900d59ff1464fc23a9265ab4f0a8161 Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:34:54 -0500 Subject: [PATCH 10/18] =?UTF-8?q?=E2=9A=99=EF=B8=8F=20Add=20npm=20script?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 4da9eae7..c1bf0f66 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "compile": "forge build", "test": "forge test --fork-url $(grep OPTIMISM_GOERLI_RPC_URL .env | cut -d '=' -f2) --etherscan-api-key $(grep OPTIMISM_ETHERSCAN_API_KEY .env | cut -d '=' -f2) --gas-report -vvv", + "test:hh": "npx hardhat test", "format": "forge fmt", "coverage": "forge coverage --fork-url $(grep OPTIMISM_GOERLI_RPC_URL .env | cut -d '=' -f2)", "coverage:generate-lcov": "forge coverage --fork-url $(grep OPTIMISM_GOERLI_RPC_URL .env | cut -d '=' -f2) --report lcov", From 688be49b640acc3b979a75b6d9593749ce33657a Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:35:14 -0500 Subject: [PATCH 11/18] =?UTF-8?q?=F0=9F=93=B8=20Update=20gas-snapshot/lcov?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 151 +++++++------ lcov.info | 607 ++++++++++++++++++++++++-------------------------- 2 files changed, 370 insertions(+), 388 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index b17a071e..82a7d114 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,103 +1,102 @@ AccountDelegate:test_isAccountDelegate_account_doesnt_exist() (gas: 26492) -AccountDelegate:test_isAccountDelegate_false() (gas: 391973) +AccountDelegate:test_isAccountDelegate_false() (gas: 391995) AccountDelegate:test_isAccountDelegate_true() (gas: 389942) -AccountDelegate:test_isAccountDelegate_zero_address_caller() (gas: 23137) -AccountOwner:test_isAccountOwner_account_doesnt_exist() (gas: 25044) -AccountOwner:test_isAccountOwner_false() (gas: 229869) -AccountOwner:test_isAccountOwner_true() (gas: 229792) -AccountOwner:test_isAccountOwner_zero_address_caller() (gas: 10808) -Aggregate:test_aggregate_EIP7412Mock(bytes) (runs: 256, μ: 46959, ~: 46854) -Aggregate:test_aggregate_EIP7412MockRefund(bytes) (runs: 256, μ: 53003, ~: 52900) +AccountDelegate:test_isAccountDelegate_zero_address_caller() (gas: 23159) +AccountOwner:test_isAccountOwner_account_doesnt_exist() (gas: 25088) +AccountOwner:test_isAccountOwner_false() (gas: 229890) +AccountOwner:test_isAccountOwner_true() (gas: 229880) +AccountOwner:test_isAccountOwner_zero_address_caller() (gas: 10829) +Aggregate:test_aggregate_EIP7412Mock(bytes) (runs: 256, μ: 46915, ~: 46810) +Aggregate:test_aggregate_EIP7412MockRefund(bytes) (runs: 256, μ: 53026, ~: 52923) Aggregate:test_aggregate_EIP7412MockRevert(bytes) (runs: 256, μ: 46046, ~: 45943) -Aggregate:test_aggregate_EIP7412Mock_fail(bytes) (runs: 256, μ: 25958, ~: 25855) +Aggregate:test_aggregate_EIP7412Mock_fail(bytes) (runs: 256, μ: 25935, ~: 25832) Aggregate:test_aggregate_EIP7412_multiple(bytes) (runs: 256, μ: 33894, ~: 33786) -Aggregate:test_aggregate_MismatchedValue_multiple() (gas: 52945) -Aggregate:test_aggregate_MismatchedValue_single() (gas: 32753) -Aggregate:test_aggregate_TargetNotTrusted() (gas: 17792) +Aggregate:test_aggregate_MismatchedValue_multiple() (gas: 52923) +Aggregate:test_aggregate_MismatchedValue_single() (gas: 32775) +Aggregate:test_aggregate_TargetNotTrusted() (gas: 17834) Aggregate:test_aggregate_empty() (gas: 6605) -Aggregate:test_aggregate_multiple() (gas: 51443) -Aggregate:test_aggregate_refund() (gas: 38977) +Aggregate:test_aggregate_multiple() (gas: 51400) +Aggregate:test_aggregate_refund() (gas: 38955) Aggregate:test_aggregate_result() (gas: 55683) Aggregate:test_aggregate_single() (gas: 15208) -Aggregate:test_aggregate_value_multiple() (gas: 51872) -Aggregate:test_aggregate_value_single(uint256) (runs: 256, μ: 24850, ~: 29208) -CanExecute:test_canExecute_false_insufficent_account_credit() (gas: 414843) -CanExecute:test_canExecute_false_invalid_signature() (gas: 446777) -CanExecute:test_canExecute_false_invalid_signer() (gas: 442066) -CanExecute:test_canExecute_false_maxExecutorFee_exceeded() (gas: 397556) -CanExecute:test_canExecute_false_nonce_used() (gas: 827190) -CanExecute:test_canExecute_false_trusted_executor() (gas: 439522) -CanExecute:test_canExecute_true() (gas: 439161) -CommitOrder:test_commitOrder() (gas: 383122) -CommitOrder:test_commitOrder_insufficient_collateral() (gas: 441342) -CommitOrder:test_commitOrder_invalid_market() (gas: 38479) +Aggregate:test_aggregate_value_multiple() (gas: 51915) +Aggregate:test_aggregate_value_single(uint256) (runs: 256, μ: 24828, ~: 29186) +CanExecute:test_canExecute_false_insufficent_account_credit() (gas: 414818) +CanExecute:test_canExecute_false_invalid_signature() (gas: 446729) +CanExecute:test_canExecute_false_invalid_signer() (gas: 441990) +CanExecute:test_canExecute_false_maxExecutorFee_exceeded() (gas: 397486) +CanExecute:test_canExecute_false_nonce_used() (gas: 827209) +CanExecute:test_canExecute_false_trusted_executor() (gas: 439497) +CanExecute:test_canExecute_true() (gas: 439136) +CommitOrder:test_commitOrder() (gas: 383166) +CommitOrder:test_commitOrder_insufficient_collateral() (gas: 441323) +CommitOrder:test_commitOrder_invalid_market() (gas: 38457) Conditions:test_isMarketOpen() (gas: 26596) -Conditions:test_isOrderFeeBelow() (gas: 179759) -Conditions:test_isPositionSizeAbove() (gas: 18801) -Conditions:test_isPositionSizeBelow() (gas: 18740) -Conditions:test_isPriceAbove() (gas: 19098) -Conditions:test_isPriceBelow() (gas: 19070) -Conditions:test_isTimestampAfter() (gas: 7734) -Conditions:test_isTimestampBefore() (gas: 7602) -Context:test_context_trustedForwarder() (gas: 13120) -DeploymentTest:test_deploy() (gas: 3540958) -DeploymentTest:test_deploy_oracle_zero_address() (gas: 422896) -DeploymentTest:test_deploy_perps_market_proxy_zero_address() (gas: 422790) -DeploymentTest:test_deploy_spot_market_proxy_zero_address() (gas: 422813) -DeploymentTest:test_deploy_susd_proxy_zero_address() (gas: 422892) -Deposit:test_depositEth() (gas: 55221) -Deposit:test_depositEth_Account_Doesnt_Exist() (gas: 34292) -Deposit:test_depositEth_event() (gas: 56837) -Deposit:test_depositEth_fuzz(uint256,uint128) (runs: 256, μ: 36335, ~: 34844) +Conditions:test_isOrderFeeBelow() (gas: 179894) +Conditions:test_isPositionSizeAbove() (gas: 18827) +Conditions:test_isPositionSizeBelow() (gas: 18732) +Conditions:test_isPriceAbove() (gas: 196191) +Conditions:test_isPriceBelow() (gas: 195969) +Conditions:test_isTimestampAfter() (gas: 7645) +Conditions:test_isTimestampBefore() (gas: 7579) +Context:test_context_trustedForwarder() (gas: 13142) +DeploymentTest:test_deploy() (gas: 3485101) +DeploymentTest:test_deploy_perps_market_proxy_zero_address() (gas: 422450) +DeploymentTest:test_deploy_spot_market_proxy_zero_address() (gas: 422517) +DeploymentTest:test_deploy_susd_proxy_zero_address() (gas: 422508) +Deposit:test_depositEth() (gas: 55243) +Deposit:test_depositEth_Account_Doesnt_Exist() (gas: 34248) +Deposit:test_depositEth_event() (gas: 56770) +Deposit:test_depositEth_fuzz(uint256,uint128) (runs: 256, μ: 36454, ~: 34866) DepositCollateral:test_depositCollateral() (gas: 258627) DepositCollateral:test_depositCollateral_availableMargin() (gas: 266195) DepositCollateral:test_depositCollateral_collateralAmount() (gas: 259203) -DepositCollateral:test_depositCollateral_insufficient_balance() (gas: 56143) -DepositCollateral:test_depositCollateral_totalCollateralValue() (gas: 263579) -EIP7412Test:test_fulfillOracleQuery(bytes) (runs: 256, μ: 153348, ~: 153344) -EIP7412Test:test_fulfillOracleQuery_refund(bytes) (runs: 256, μ: 161857, ~: 161853) -EIP7412Test:test_fulfillOracleQuery_revert(bytes) (runs: 256, μ: 154898, ~: 154894) -Execute:test_execute_CannotExecuteOrder_invalid_acceptablePrice() (gas: 331759) -Execute:test_execute_CannotExecuteOrder_invalid_settlementStrategyId() (gas: 97680) -Execute:test_execute_CannotExecuteOrder_too_leveraged() (gas: 362398) -Execute:test_execute_event() (gas: 434742) -Execute:test_execute_order_committed() (gas: 431256) -Fee:test_fee_exceeds_account_credit() (gas: 67949) -Fee:test_fee_exceeds_maxExecutorFee() (gas: 67484) -Fee:test_fee_imposed() (gas: 469443) +DepositCollateral:test_depositCollateral_insufficient_balance() (gas: 56208) +DepositCollateral:test_depositCollateral_totalCollateralValue() (gas: 263557) +EIP7412Test:test_fulfillOracleQuery(bytes) (runs: 256, μ: 153304, ~: 153300) +EIP7412Test:test_fulfillOracleQuery_refund(bytes) (runs: 256, μ: 161879, ~: 161875) +EIP7412Test:test_fulfillOracleQuery_revert(bytes) (runs: 256, μ: 154920, ~: 154916) +Execute:test_execute_CannotExecuteOrder_invalid_acceptablePrice() (gas: 331736) +Execute:test_execute_CannotExecuteOrder_invalid_settlementStrategyId() (gas: 97657) +Execute:test_execute_CannotExecuteOrder_too_leveraged() (gas: 362331) +Execute:test_execute_event() (gas: 434764) +Execute:test_execute_order_committed() (gas: 431211) +Fee:test_fee_exceeds_account_credit() (gas: 67862) +Fee:test_fee_exceeds_maxExecutorFee() (gas: 67464) +Fee:test_fee_imposed() (gas: 469423) MathLibTest:test_abs128() (gas: 425) MathLibTest:test_abs256() (gas: 480) MathLibTest:test_fuzz_abs128(int128) (runs: 256, μ: 577, ~: 603) MathLibTest:test_fuzz_abs256(int256) (runs: 256, μ: 472, ~: 458) MathLibTest:test_isSameSign() (gas: 999) -NonceBitmapTest:test_fuzz_invalidateUnorderedNonces(uint256) (runs: 256, μ: 52898, ~: 52898) -NonceBitmapTest:test_hasUnorderedNonceBeenUsed() (gas: 54254) -NonceBitmapTest:test_invalidateUnorderedNonces() (gas: 77406) -NonceBitmapTest:test_invalidateUnorderedNonces_Only_Owner_Delegate() (gas: 190580) +NonceBitmapTest:test_fuzz_invalidateUnorderedNonces(uint256) (runs: 256, μ: 52920, ~: 52920) +NonceBitmapTest:test_hasUnorderedNonceBeenUsed() (gas: 54209) +NonceBitmapTest:test_invalidateUnorderedNonces() (gas: 77434) +NonceBitmapTest:test_invalidateUnorderedNonces_Only_Owner_Delegate() (gas: 190646) NonceBitmapTest:test_invalidateUnorderedNonces_event() (gas: 53592) -ReduceOnly:test_reduce_only() (gas: 433034) -ReduceOnly:test_reduce_only_same_sign() (gas: 73963) -ReduceOnly:test_reduce_only_truncate_size_down() (gas: 433076) -ReduceOnly:test_reduce_only_truncate_size_up() (gas: 409825) -ReduceOnly:test_reduce_only_when_position_doesnt_exist() (gas: 163808) +ReduceOnly:test_reduce_only() (gas: 432946) +ReduceOnly:test_reduce_only_same_sign() (gas: 73941) +ReduceOnly:test_reduce_only_truncate_size_down() (gas: 433054) +ReduceOnly:test_reduce_only_truncate_size_up() (gas: 409803) +ReduceOnly:test_reduce_only_when_position_doesnt_exist() (gas: 163763) ReduceOnly:test_reduce_only_zero_size_delta() (gas: 164392) -VerifyConditions:test_max_condition_size_exceeded() (gas: 45101) -VerifyConditions:test_verifyConditions_InvalidConditionSelector() (gas: 14133) -VerifyConditions:test_verify_conditions_not_verified() (gas: 29707) -VerifyConditions:test_verify_conditions_verified() (gas: 135835) -VerifySignature:test_verifySignature(uint256) (runs: 256, μ: 24994, ~: 24994) -VerifySignature:test_verifySignature_false_private_key() (gas: 24970) -VerifySigner:test_verifySigner() (gas: 25917) +VerifyConditions:test_max_condition_size_exceeded() (gas: 45071) +VerifyConditions:test_verifyConditions_InvalidConditionSelector() (gas: 14081) +VerifyConditions:test_verify_conditions_not_verified() (gas: 129150) +VerifyConditions:test_verify_conditions_verified() (gas: 183733) +VerifySignature:test_verifySignature(uint256) (runs: 256, μ: 24992, ~: 24992) +VerifySignature:test_verifySignature_false_private_key() (gas: 24968) +VerifySigner:test_verifySigner() (gas: 25939) VerifySigner:test_verifySigner_false() (gas: 28647) Withdraw:test_withdrawEth() (gas: 52652) Withdraw:test_withdrawEth_EthTransferFailed() (gas: 93200) Withdraw:test_withdrawEth_InsufficientEthBalance() (gas: 59867) Withdraw:test_withdrawEth_Unauthorized() (gas: 59616) -Withdraw:test_withdrawEth_event() (gas: 51896) -Withdraw:test_withdrawEth_fuzz(uint256) (runs: 256, μ: 71047, ~: 71597) +Withdraw:test_withdrawEth_event() (gas: 51878) +Withdraw:test_withdrawEth_fuzz(uint256) (runs: 256, μ: 71114, ~: 71664) WithdrawCollateral:test_withdrawCollateral() (gas: 353419) -WithdrawCollateral:test_withdrawCollateral_availableMargin() (gas: 354937) +WithdrawCollateral:test_withdrawCollateral_availableMargin() (gas: 354955) WithdrawCollateral:test_withdrawCollateral_collateralAmount() (gas: 353929) WithdrawCollateral:test_withdrawCollateral_insufficient_account_collateral_balance() (gas: 274470) -WithdrawCollateral:test_withdrawCollateral_totalCollateralValue() (gas: 354436) +WithdrawCollateral:test_withdrawCollateral_totalCollateralValue() (gas: 354418) WithdrawCollateral:test_withdrawCollateral_zero() (gas: 266428) \ No newline at end of file diff --git a/lcov.info b/lcov.info index c9cb594b..38215c3f 100644 --- a/lcov.info +++ b/lcov.info @@ -1,44 +1,44 @@ TN: SF:script/Deploy.s.sol -FN:122,DeployOptimism_Synthetix.run -FNDA:0,DeployOptimism_Synthetix.run -DA:123,0 -DA:124,0 -DA:126,0 -DA:133,0 -FN:43,DeployBase_Synthetix.run +FN:41,DeployBase_Synthetix.run FNDA:0,DeployBase_Synthetix.run -DA:44,0 +DA:42,0 +DA:43,0 DA:45,0 -DA:47,0 -DA:54,0 +DA:51,0 FN:24,Setup.deploySystem -FNDA:5,Setup.deploySystem -DA:30,5 -FN:141,DeployOptimismGoerli_Synthetix.run -FNDA:0,DeployOptimismGoerli_Synthetix.run -DA:142,0 -DA:143,0 -DA:145,0 -DA:152,0 -FN:62,DeployBaseGoerli_Synthetix.run +FNDA:4,Setup.deploySystem +DA:29,4 +FN:98,DeployBaseGoerli_Andromeda.run +FNDA:0,DeployBaseGoerli_Andromeda.run +DA:99,0 +DA:100,0 +DA:102,0 +DA:108,0 +FN:80,DeployBaseGoerli_KwentaFork.run +FNDA:0,DeployBaseGoerli_KwentaFork.run +DA:81,0 +DA:82,0 +DA:84,0 +DA:90,0 +FN:116,DeployOptimism_Synthetix.run +FNDA:0,DeployOptimism_Synthetix.run +DA:117,0 +DA:118,0 +DA:120,0 +DA:126,0 +FN:59,DeployBaseGoerli_Synthetix.run FNDA:0,DeployBaseGoerli_Synthetix.run +DA:60,0 +DA:61,0 DA:63,0 -DA:64,0 -DA:66,0 -DA:73,0 -FN:84,DeployBaseGoerli_KwentaFork.run -FNDA:0,DeployBaseGoerli_KwentaFork.run -DA:85,0 -DA:86,0 -DA:88,0 -DA:95,0 -FN:103,DeployBaseGoerli_Andromeda.run -FNDA:0,DeployBaseGoerli_Andromeda.run -DA:104,0 -DA:105,0 -DA:107,0 -DA:114,0 +DA:69,0 +FN:134,DeployOptimismGoerli_Synthetix.run +FNDA:0,DeployOptimismGoerli_Synthetix.run +DA:135,0 +DA:136,0 +DA:138,0 +DA:144,0 FNF:7 FNH:1 LF:25 @@ -48,224 +48,224 @@ BRH:0 end_of_record TN: SF:src/Engine.sol -FN:123,Engine.trustedForwarder +FN:115,Engine.trustedForwarder FNDA:1,Engine.trustedForwarder -DA:124,1852 -FN:132,Engine.isAccountOwner +DA:116,1852 +FN:124,Engine.isAccountOwner FNDA:4,Engine.isAccountOwner -DA:138,271 -DA:139,270 -FN:143,Engine.isAccountDelegate +DA:130,271 +DA:131,270 +FN:135,Engine.isAccountDelegate FNDA:3,Engine.isAccountDelegate -DA:149,3 -FN:154,Engine._isAccountOwnerOrDelegate +DA:141,3 +FN:146,Engine._isAccountOwnerOrDelegate FNDA:284,Engine._isAccountOwnerOrDelegate -DA:159,284 -DA:160,284 -FN:170,Engine.depositEth +DA:151,284 +DA:152,284 +FN:162,Engine.depositEth FNDA:523,Engine.depositEth -DA:173,523 -BRDA:173,0,0,229 -BRDA:173,0,1,294 -DA:174,229 -DA:177,294 -DA:179,294 -FN:183,Engine.withdrawEth +DA:165,523 +BRDA:165,0,0,245 +BRDA:165,0,1,278 +DA:166,245 +DA:169,278 +DA:171,278 +FN:175,Engine.withdrawEth FNDA:261,Engine.withdrawEth -DA:187,261 -DA:189,261 -BRDA:189,1,0,1 -BRDA:189,1,1,260 -DA:191,260 -DA:193,258 -FN:200,Engine._withdrawEth +DA:179,261 +DA:181,261 +BRDA:181,1,0,1 +BRDA:181,1,1,260 +DA:183,260 +DA:185,258 +FN:192,Engine._withdrawEth FNDA:273,Engine._withdrawEth -DA:203,273 -BRDA:203,2,0,1 -BRDA:203,2,1,272 -DA:206,272 -DA:208,272 -DA:210,272 -BRDA:210,3,0,1 -BRDA:210,3,1,271 -FN:218,Engine.invalidateUnorderedNonces +DA:195,273 +BRDA:195,2,0,1 +BRDA:195,2,1,272 +DA:198,272 +DA:200,272 +DA:202,272 +BRDA:202,3,0,1 +BRDA:202,3,1,271 +FN:210,Engine.invalidateUnorderedNonces FNDA:261,Engine.invalidateUnorderedNonces +DA:215,261 +BRDA:215,4,0,261 +BRDA:215,4,1,- +DA:221,261 DA:223,261 -BRDA:223,4,0,261 -BRDA:223,4,1,- -DA:229,261 -DA:231,261 -DA:233,0 -FN:238,Engine.hasUnorderedNonceBeenUsed +DA:225,0 +FN:230,Engine.hasUnorderedNonceBeenUsed FNDA:260,Engine.hasUnorderedNonceBeenUsed -DA:244,280 -DA:248,280 -DA:262,280 -FN:272,Engine._bitmapPositions +DA:236,280 +DA:240,280 +DA:254,280 +FN:264,Engine._bitmapPositions FNDA:293,Engine._bitmapPositions -DA:279,293 -DA:283,293 -FN:289,Engine._useUnorderedNonce +DA:271,293 +DA:275,293 +FN:281,Engine._useUnorderedNonce FNDA:13,Engine._useUnorderedNonce -DA:290,13 -DA:294,13 -DA:301,13 -DA:321,13 -BRDA:321,5,0,- -BRDA:321,5,1,13 -FN:329,Engine.modifyCollateral +DA:282,13 +DA:286,13 +DA:293,13 +DA:313,13 +BRDA:313,5,0,- +BRDA:313,5,1,13 +FN:321,Engine.modifyCollateral FNDA:17,Engine.modifyCollateral -DA:334,17 -DA:336,17 -DA:338,17 -BRDA:338,6,0,11 -BRDA:338,6,1,6 -DA:339,11 -DA:343,6 -BRDA:343,7,0,- -BRDA:343,7,1,6 -DA:344,6 -FN:350,Engine._depositCollateral +DA:326,17 +DA:328,17 +DA:330,17 +BRDA:330,6,0,11 +BRDA:330,6,1,6 +DA:331,11 +DA:335,6 +BRDA:335,7,0,- +BRDA:335,7,1,6 +DA:336,6 +FN:342,Engine._depositCollateral FNDA:11,Engine._depositCollateral -DA:358,11 -DA:360,10 -DA:362,10 -FN:365,Engine._withdrawCollateral +DA:350,11 +DA:352,10 +DA:354,10 +FN:357,Engine._withdrawCollateral FNDA:6,Engine._withdrawCollateral -DA:372,6 -DA:375,4 -FN:381,Engine._getSynthAddress +DA:364,6 +DA:367,4 +FN:373,Engine._getSynthAddress FNDA:17,Engine._getSynthAddress -DA:386,17 -FN:396,Engine.commitOrder +DA:378,17 +FN:388,Engine.commitOrder FNDA:3,Engine.commitOrder -DA:410,3 -BRDA:410,8,0,3 -BRDA:410,8,1,- -DA:411,3 -DA:421,0 -FN:425,Engine._commitOrder +DA:402,3 +BRDA:402,8,0,3 +BRDA:402,8,1,- +DA:403,3 +DA:413,0 +FN:417,Engine._commitOrder FNDA:13,Engine._commitOrder -DA:434,13 -FN:452,Engine.execute +DA:426,13 +FN:444,Engine.execute FNDA:15,Engine.execute -DA:467,15 -BRDA:467,9,0,2 -BRDA:467,9,1,13 -DA:470,13 -DA:476,13 -DA:479,13 -DA:482,13 -BRDA:482,10,0,2 -BRDA:482,10,1,3 -DA:483,6 -DA:488,6 -BRDA:488,11,0,2 -BRDA:488,11,1,4 -DA:489,2 -DA:494,4 -BRDA:494,12,0,1 -BRDA:494,12,1,3 -DA:495,1 -DA:501,3 -BRDA:501,13,0,2 -BRDA:501,13,1,3 -DA:511,2 -DA:516,10 -DA:526,7 -FN:534,Engine.canExecute +DA:459,15 +BRDA:459,9,0,2 +BRDA:459,9,1,13 +DA:462,13 +DA:468,13 +DA:471,13 +DA:474,13 +BRDA:474,10,0,2 +BRDA:474,10,1,3 +DA:475,6 +DA:480,6 +BRDA:480,11,0,2 +BRDA:480,11,1,4 +DA:481,2 +DA:486,4 +BRDA:486,12,0,1 +BRDA:486,12,1,3 +DA:487,1 +DA:493,3 +BRDA:493,13,0,2 +BRDA:493,13,1,3 +DA:503,2 +DA:508,10 +DA:518,7 +FN:526,Engine.canExecute FNDA:9,Engine.canExecute -DA:540,24 -BRDA:540,14,0,2 -BRDA:540,14,1,22 -DA:543,22 -BRDA:543,15,0,2 -BRDA:543,15,1,20 -DA:546,20 -BRDA:546,16,0,2 -BRDA:546,16,1,18 -DA:547,2 -DA:551,18 -BRDA:551,17,0,1 -BRDA:551,17,1,17 -DA:554,17 -BRDA:554,18,0,1 -BRDA:554,18,1,16 -DA:557,16 -BRDA:557,19,0,- -BRDA:557,19,1,- -DA:560,0 -BRDA:560,20,0,- -BRDA:560,20,1,- -DA:564,16 -BRDA:564,21,0,1 -BRDA:564,21,1,15 -DA:567,15 -FN:575,Engine.verifySigner +DA:532,24 +BRDA:532,14,0,2 +BRDA:532,14,1,22 +DA:535,22 +BRDA:535,15,0,2 +BRDA:535,15,1,20 +DA:538,20 +BRDA:538,16,0,2 +BRDA:538,16,1,18 +DA:539,2 +DA:543,18 +BRDA:543,17,0,1 +BRDA:543,17,1,17 +DA:546,17 +BRDA:546,18,0,1 +BRDA:546,18,1,16 +DA:549,16 +BRDA:549,19,0,- +BRDA:549,19,1,- +DA:552,0 +BRDA:552,20,0,- +BRDA:552,20,1,- +DA:556,16 +BRDA:556,21,0,1 +BRDA:556,21,1,15 +DA:559,15 +FN:567,Engine.verifySigner FNDA:2,Engine.verifySigner -DA:581,20 -FN:585,Engine.verifySignature +DA:573,20 +FN:577,Engine.verifySignature FNDA:257,Engine.verifySignature -DA:589,274 -FN:593,Engine.verifyConditions +DA:581,274 +FN:585,Engine.verifyConditions FNDA:4,Engine.verifyConditions -DA:599,4 -DA:600,4 -BRDA:600,22,0,1 -BRDA:600,22,1,3 -DA:601,1 -DA:604,3 -DA:605,13 +DA:591,4 +DA:592,4 +BRDA:592,22,0,1 +BRDA:592,22,1,3 +DA:593,1 +DA:596,3 +DA:597,13 +DA:598,13 +DA:601,13 DA:606,13 -DA:609,13 -DA:614,13 -DA:615,11 -DA:616,9 -DA:617,7 -DA:618,5 -DA:619,4 -DA:620,3 -DA:621,2 -BRDA:613,23,0,1 -BRDA:613,23,1,11 -DA:624,12 -DA:627,12 -BRDA:627,24,0,1 -BRDA:627,24,1,11 -DA:630,11 -DA:633,1 -DA:637,1 -FN:645,Engine.isTimestampAfter +DA:607,11 +DA:608,9 +DA:609,7 +DA:610,5 +DA:611,4 +DA:612,3 +DA:613,2 +BRDA:605,23,0,1 +BRDA:605,23,1,11 +DA:616,12 +DA:619,12 +BRDA:619,24,0,1 +BRDA:619,24,1,11 +DA:622,11 +DA:625,1 +DA:629,1 +FN:637,Engine.isTimestampAfter FNDA:5,Engine.isTimestampAfter -DA:651,5 -FN:655,Engine.isTimestampBefore +DA:643,5 +FN:647,Engine.isTimestampBefore FNDA:5,Engine.isTimestampBefore -DA:661,5 -FN:665,Engine.isPriceAbove +DA:653,5 +FN:657,Engine.isPriceAbove FNDA:6,Engine.isPriceAbove -DA:670,6 -DA:675,6 -FN:679,Engine.isPriceBelow +DA:663,6 +DA:668,6 +FN:672,Engine.isPriceBelow FNDA:6,Engine.isPriceBelow -DA:684,6 -DA:689,6 -FN:693,Engine.isMarketOpen +DA:678,6 +DA:683,6 +FN:687,Engine.isMarketOpen FNDA:3,Engine.isMarketOpen -DA:699,3 -FN:703,Engine.isPositionSizeAbove +DA:693,3 +FN:697,Engine.isPositionSizeAbove FNDA:4,Engine.isPositionSizeAbove -DA:708,4 -DA:709,4 -DA:711,4 -FN:715,Engine.isPositionSizeBelow +DA:702,4 +DA:703,4 +DA:705,4 +FN:709,Engine.isPositionSizeBelow FNDA:4,Engine.isPositionSizeBelow -DA:720,4 -DA:721,4 -DA:723,4 -FN:727,Engine.isOrderFeeBelow +DA:714,4 +DA:715,4 +DA:717,4 +FN:721,Engine.isOrderFeeBelow FNDA:4,Engine.isOrderFeeBelow -DA:733,4 -DA:738,4 +DA:727,4 +DA:732,4 FNF:30 FNH:30 LF:108 @@ -432,42 +432,42 @@ end_of_record TN: SF:src/utils/TrustedForwarder.sol FN:30,TrustedForwarder.aggregate -FNDA:1451,TrustedForwarder.aggregate -DA:35,1451 -DA:36,1451 -DA:38,1451 -DA:39,1451 -DA:41,1451 -DA:43,1458 -DA:47,1458 +FNDA:1452,TrustedForwarder.aggregate +DA:35,1452 +DA:36,1452 +DA:38,1452 +DA:39,1452 +DA:41,1452 +DA:43,1459 +DA:47,1459 BRDA:47,0,0,1 -BRDA:47,0,1,1457 +BRDA:47,0,1,1458 DA:48,1 -DA:52,1457 -DA:57,1457 -DA:60,1457 -DA:67,1457 +DA:52,1458 +DA:57,1458 +DA:60,1458 +DA:67,1458 BRDA:67,1,0,1026 -BRDA:67,1,1,431 +BRDA:67,1,1,432 DA:68,1026 DA:69,1026 -DA:75,431 -DA:78,431 -DA:83,424 +DA:75,432 +DA:78,432 +DA:83,425 BRDA:83,2,0,2 -BRDA:83,2,1,422 +BRDA:83,2,1,423 DA:84,2 FN:91,TrustedForwarder._isTrustedByTarget -FNDA:1458,TrustedForwarder._isTrustedByTarget -DA:92,1458 -DA:93,1458 -DA:95,1458 -DA:96,1458 -DA:97,1458 -DA:105,1458 -DA:114,1458 -DA:115,1458 -DA:118,1458 +FNDA:1459,TrustedForwarder._isTrustedByTarget +DA:92,1459 +DA:93,1459 +DA:95,1459 +DA:96,1459 +DA:97,1459 +DA:105,1459 +DA:114,1459 +DA:115,1459 +DA:118,1459 FNF:2 FNH:2 LF:27 @@ -520,21 +520,21 @@ BRH:0 end_of_record TN: SF:test/ConditionalOrder.t.sol -FN:23,ConditionalOrderTest.setUp +FN:21,ConditionalOrderTest.setUp FNDA:0,ConditionalOrderTest.setUp -DA:24,0 +DA:22,0 +DA:23,0 DA:25,0 -DA:27,0 +DA:26,0 DA:28,0 -DA:30,0 +DA:29,0 DA:31,0 DA:33,0 DA:35,0 DA:37,0 -DA:39,0 +DA:43,0 DA:45,0 -DA:47,0 -DA:53,0 +DA:51,0 FNF:1 FNH:0 LF:13 @@ -577,55 +577,53 @@ BRH:0 end_of_record TN: SF:test/utils/Bootstrap.sol -FN:134,BootstrapOptimismGoerli.init +FN:125,BootstrapOptimismGoerli.init FNDA:0,BootstrapOptimismGoerli.init -DA:138,0 -DA:145,0 -DA:152,0 -FN:38,Bootstrap.initializeOptimismGoerli +DA:129,0 +DA:135,0 +DA:141,0 +FN:36,Bootstrap.initializeOptimismGoerli FNDA:0,Bootstrap.initializeOptimismGoerli -DA:39,0 -DA:40,0 +DA:37,0 +DA:38,0 +DA:44,0 +DA:46,0 DA:47,0 +DA:48,0 DA:49,0 DA:50,0 DA:51,0 DA:52,0 -DA:53,0 DA:54,0 DA:55,0 DA:56,0 -DA:58,0 -DA:59,0 -DA:60,0 -DA:65,0 -DA:67,0 -FN:70,Bootstrap.initializeOptimism +DA:61,0 +DA:63,0 +FN:66,Bootstrap.initializeOptimism FNDA:0,Bootstrap.initializeOptimism -DA:71,0 -DA:72,0 +DA:67,0 +DA:68,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:78,0 DA:79,0 +DA:80,0 DA:81,0 DA:82,0 -DA:83,0 DA:84,0 DA:85,0 DA:86,0 -DA:87,0 -DA:88,0 -DA:90,0 DA:91,0 -DA:92,0 -DA:97,0 -DA:99,0 -FN:104,BootstrapOptimism.init +DA:93,0 +FN:98,BootstrapOptimism.init FNDA:0,BootstrapOptimism.init +DA:102,0 DA:108,0 -DA:115,0 -DA:122,0 +DA:114,0 FNF:4 FNH:0 -LF:38 +LF:36 LH:0 BRF:0 BRH:0 @@ -702,9 +700,9 @@ BRH:0 end_of_record TN: SF:test/utils/exposed/EngineExposed.sol -FN:16,EngineExposed.getSynthAddress +FN:15,EngineExposed.getSynthAddress FNDA:0,EngineExposed.getSynthAddress -DA:21,0 +DA:20,0 FNF:1 FNH:0 LF:1 @@ -714,6 +712,9 @@ BRH:0 end_of_record TN: SF:test/utils/mocks/EIP7412Mock.sol +FN:23,EIP7412MockRevert.fulfillOracleQuery +FNDA:512,EIP7412MockRevert.fulfillOracleQuery +DA:24,512 FN:15,EIP7412MockRefund.fulfillOracleQuery FNDA:512,EIP7412MockRefund.fulfillOracleQuery DA:16,512 @@ -723,9 +724,6 @@ DA:17,512 DA:18,512 BRDA:18,1,0,512 BRDA:18,1,1,- -FN:23,EIP7412MockRevert.fulfillOracleQuery -FNDA:512,EIP7412MockRevert.fulfillOracleQuery -DA:24,512 FN:7,EIP7412Mock.fulfillOracleQuery FNDA:1024,EIP7412Mock.fulfillOracleQuery DA:8,1024 @@ -761,8 +759,8 @@ DA:29,1 BRDA:29,1,0,1 BRDA:29,1,1,- FN:32,MockCalleeWithContext.lockEth -FNDA:172,MockCalleeWithContext.lockEth -DA:34,172 +FNDA:173,MockCalleeWithContext.lockEth +DA:34,173 FNF:6 FNH:4 LF:6 @@ -771,34 +769,19 @@ BRF:4 BRH:2 end_of_record TN: -SF:test/utils/mocks/PythMock.sol -FN:8,PythMock.mock_pyth_getPrice -FNDA:0,PythMock.mock_pyth_getPrice -DA:15,0 -FNF:1 -FNH:0 -LF:1 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: SF:test/utils/mocks/SynthetixMock.sol -FN:8,SynthetixMock.mock_computeOrderFees -FNDA:0,SynthetixMock.mock_computeOrderFees -DA:15,0 -FN:24,SynthetixMock.mock_getOpenPosition +FN:8,SynthetixMock.mock_getOpenPosition FNDA:0,SynthetixMock.mock_getOpenPosition -DA:30,0 -FN:39,SynthetixMock.mock_getMaxMarketSize +DA:14,0 +FN:23,SynthetixMock.mock_getMaxMarketSize FNDA:0,SynthetixMock.mock_getMaxMarketSize -DA:44,0 -FN:53,SynthetixMock.mock_getAccountOwner +DA:28,0 +FN:37,SynthetixMock.mock_getAccountOwner FNDA:0,SynthetixMock.mock_getAccountOwner -DA:58,0 -FNF:4 +DA:42,0 +FNF:3 FNH:0 -LF:4 +LF:3 LH:0 BRF:0 BRH:0 From 4ae03e82d250f5b74925caf02b0471f4d69effca Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:44:29 -0500 Subject: [PATCH 12/18] =?UTF-8?q?=E2=9C=85=20Add=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/AsyncOrder.t.sol | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/AsyncOrder.t.sol b/test/AsyncOrder.t.sol index 047f38d3..956c00d6 100644 --- a/test/AsyncOrder.t.sol +++ b/test/AsyncOrder.t.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.20; import {Bootstrap} from "test/utils/Bootstrap.sol"; +import {IEngine} from "src/interfaces/IEngine.sol"; import {IPerpsMarketProxy} from "src/interfaces/synthetix/IPerpsMarketProxy.sol"; import {SynthetixMock} from "test/utils/mocks/SynthetixMock.sol"; @@ -102,4 +103,21 @@ contract CommitOrder is AsyncOrderTest { _referrer: REFERRER }); } + + function test_commitOrder_Unauthorized() public { + vm.prank(BAD_ACTOR); + + vm.expectRevert(abi.encodeWithSelector(IEngine.Unauthorized.selector)); + + (IPerpsMarketProxy.Data memory retOrder, uint256 fees) = engine + .commitOrder({ + _perpsMarketId: SETH_PERPS_MARKET_ID, + _accountId: accountId, + _sizeDelta: 1 ether, + _settlementStrategyId: SETTLEMENT_STRATEGY_ID, + _acceptablePrice: type(uint256).max, + _trackingCode: TRACKING_CODE, + _referrer: REFERRER + }); + } } From 8837d58874243fe648f03580ec530c4c1deb611b Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:45:05 -0500 Subject: [PATCH 13/18] =?UTF-8?q?=F0=9F=93=B8=20Update=20gas-snapshot/lcov?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 3 +- lcov.info | 160 +++++++++++++++++++++++++------------------------- 2 files changed, 82 insertions(+), 81 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 82a7d114..2871b775 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -29,8 +29,9 @@ CanExecute:test_canExecute_false_nonce_used() (gas: 827209) CanExecute:test_canExecute_false_trusted_executor() (gas: 439497) CanExecute:test_canExecute_true() (gas: 439136) CommitOrder:test_commitOrder() (gas: 383166) +CommitOrder:test_commitOrder_Unauthorized() (gas: 33210) CommitOrder:test_commitOrder_insufficient_collateral() (gas: 441323) -CommitOrder:test_commitOrder_invalid_market() (gas: 38457) +CommitOrder:test_commitOrder_invalid_market() (gas: 38435) Conditions:test_isMarketOpen() (gas: 26596) Conditions:test_isOrderFeeBelow() (gas: 179894) Conditions:test_isPositionSizeAbove() (gas: 18827) diff --git a/lcov.info b/lcov.info index 38215c3f..8e6629ae 100644 --- a/lcov.info +++ b/lcov.info @@ -1,26 +1,26 @@ TN: SF:script/Deploy.s.sol -FN:41,DeployBase_Synthetix.run -FNDA:0,DeployBase_Synthetix.run -DA:42,0 -DA:43,0 -DA:45,0 -DA:51,0 -FN:24,Setup.deploySystem -FNDA:4,Setup.deploySystem -DA:29,4 +FN:134,DeployOptimismGoerli_Synthetix.run +FNDA:0,DeployOptimismGoerli_Synthetix.run +DA:135,0 +DA:136,0 +DA:138,0 +DA:144,0 FN:98,DeployBaseGoerli_Andromeda.run FNDA:0,DeployBaseGoerli_Andromeda.run DA:99,0 DA:100,0 DA:102,0 DA:108,0 -FN:80,DeployBaseGoerli_KwentaFork.run -FNDA:0,DeployBaseGoerli_KwentaFork.run -DA:81,0 -DA:82,0 -DA:84,0 -DA:90,0 +FN:24,Setup.deploySystem +FNDA:4,Setup.deploySystem +DA:29,4 +FN:41,DeployBase_Synthetix.run +FNDA:0,DeployBase_Synthetix.run +DA:42,0 +DA:43,0 +DA:45,0 +DA:51,0 FN:116,DeployOptimism_Synthetix.run FNDA:0,DeployOptimism_Synthetix.run DA:117,0 @@ -33,12 +33,12 @@ DA:60,0 DA:61,0 DA:63,0 DA:69,0 -FN:134,DeployOptimismGoerli_Synthetix.run -FNDA:0,DeployOptimismGoerli_Synthetix.run -DA:135,0 -DA:136,0 -DA:138,0 -DA:144,0 +FN:80,DeployBaseGoerli_KwentaFork.run +FNDA:0,DeployBaseGoerli_KwentaFork.run +DA:81,0 +DA:82,0 +DA:84,0 +DA:90,0 FNF:7 FNH:1 LF:25 @@ -50,7 +50,7 @@ TN: SF:src/Engine.sol FN:115,Engine.trustedForwarder FNDA:1,Engine.trustedForwarder -DA:116,1852 +DA:116,1853 FN:124,Engine.isAccountOwner FNDA:4,Engine.isAccountOwner DA:130,271 @@ -59,17 +59,17 @@ FN:135,Engine.isAccountDelegate FNDA:3,Engine.isAccountDelegate DA:141,3 FN:146,Engine._isAccountOwnerOrDelegate -FNDA:284,Engine._isAccountOwnerOrDelegate -DA:151,284 -DA:152,284 +FNDA:285,Engine._isAccountOwnerOrDelegate +DA:151,285 +DA:152,285 FN:162,Engine.depositEth FNDA:523,Engine.depositEth DA:165,523 -BRDA:165,0,0,245 -BRDA:165,0,1,278 -DA:166,245 -DA:169,278 -DA:171,278 +BRDA:165,0,0,240 +BRDA:165,0,1,283 +DA:166,240 +DA:169,283 +DA:171,283 FN:175,Engine.withdrawEth FNDA:261,Engine.withdrawEth DA:179,261 @@ -138,12 +138,12 @@ FN:373,Engine._getSynthAddress FNDA:17,Engine._getSynthAddress DA:378,17 FN:388,Engine.commitOrder -FNDA:3,Engine.commitOrder -DA:402,3 +FNDA:4,Engine.commitOrder +DA:402,4 BRDA:402,8,0,3 -BRDA:402,8,1,- +BRDA:402,8,1,1 DA:403,3 -DA:413,0 +DA:413,1 FN:417,Engine._commitOrder FNDA:13,Engine._commitOrder DA:426,13 @@ -269,9 +269,9 @@ DA:732,4 FNF:30 FNH:30 LF:108 -LH:105 +LH:106 BRF:50 -BRH:42 +BRH:43 end_of_record TN: SF:src/libraries/ConditionalOrderHashLib.sol @@ -432,42 +432,42 @@ end_of_record TN: SF:src/utils/TrustedForwarder.sol FN:30,TrustedForwarder.aggregate -FNDA:1452,TrustedForwarder.aggregate -DA:35,1452 -DA:36,1452 -DA:38,1452 -DA:39,1452 -DA:41,1452 -DA:43,1459 -DA:47,1459 +FNDA:1441,TrustedForwarder.aggregate +DA:35,1441 +DA:36,1441 +DA:38,1441 +DA:39,1441 +DA:41,1441 +DA:43,1448 +DA:47,1448 BRDA:47,0,0,1 -BRDA:47,0,1,1458 +BRDA:47,0,1,1447 DA:48,1 -DA:52,1458 -DA:57,1458 -DA:60,1458 -DA:67,1458 +DA:52,1447 +DA:57,1447 +DA:60,1447 +DA:67,1447 BRDA:67,1,0,1026 -BRDA:67,1,1,432 +BRDA:67,1,1,421 DA:68,1026 DA:69,1026 -DA:75,432 -DA:78,432 -DA:83,425 +DA:75,421 +DA:78,421 +DA:83,414 BRDA:83,2,0,2 -BRDA:83,2,1,423 +BRDA:83,2,1,412 DA:84,2 FN:91,TrustedForwarder._isTrustedByTarget -FNDA:1459,TrustedForwarder._isTrustedByTarget -DA:92,1459 -DA:93,1459 -DA:95,1459 -DA:96,1459 -DA:97,1459 -DA:105,1459 -DA:114,1459 -DA:115,1459 -DA:118,1459 +FNDA:1448,TrustedForwarder._isTrustedByTarget +DA:92,1448 +DA:93,1448 +DA:95,1448 +DA:96,1448 +DA:97,1448 +DA:105,1448 +DA:114,1448 +DA:115,1448 +DA:118,1448 FNF:2 FNH:2 LF:27 @@ -477,14 +477,14 @@ BRH:6 end_of_record TN: SF:test/AsyncOrder.t.sol -FN:9,AsyncOrderTest.setUp +FN:10,AsyncOrderTest.setUp FNDA:0,AsyncOrderTest.setUp -DA:10,0 DA:11,0 -DA:13,0 -DA:15,0 -DA:17,0 -DA:23,0 +DA:12,0 +DA:14,0 +DA:16,0 +DA:18,0 +DA:24,0 FNF:1 FNH:0 LF:6 @@ -577,6 +577,11 @@ BRH:0 end_of_record TN: SF:test/utils/Bootstrap.sol +FN:98,BootstrapOptimism.init +FNDA:0,BootstrapOptimism.init +DA:102,0 +DA:108,0 +DA:114,0 FN:125,BootstrapOptimismGoerli.init FNDA:0,BootstrapOptimismGoerli.init DA:129,0 @@ -616,11 +621,6 @@ DA:85,0 DA:86,0 DA:91,0 DA:93,0 -FN:98,BootstrapOptimism.init -FNDA:0,BootstrapOptimism.init -DA:102,0 -DA:108,0 -DA:114,0 FNF:4 FNH:0 LF:36 @@ -712,9 +712,6 @@ BRH:0 end_of_record TN: SF:test/utils/mocks/EIP7412Mock.sol -FN:23,EIP7412MockRevert.fulfillOracleQuery -FNDA:512,EIP7412MockRevert.fulfillOracleQuery -DA:24,512 FN:15,EIP7412MockRefund.fulfillOracleQuery FNDA:512,EIP7412MockRefund.fulfillOracleQuery DA:16,512 @@ -730,6 +727,9 @@ DA:8,1024 BRDA:8,0,0,512 BRDA:8,0,1,512 DA:10,512 +FN:23,EIP7412MockRevert.fulfillOracleQuery +FNDA:512,EIP7412MockRevert.fulfillOracleQuery +DA:24,512 FNF:3 FNH:3 LF:6 @@ -759,8 +759,8 @@ DA:29,1 BRDA:29,1,0,1 BRDA:29,1,1,- FN:32,MockCalleeWithContext.lockEth -FNDA:173,MockCalleeWithContext.lockEth -DA:34,173 +FNDA:162,MockCalleeWithContext.lockEth +DA:34,162 FNF:6 FNH:4 LF:6 From f3fddf9f603069bd5af5d1c69888936f4997786c Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:49:43 -0500 Subject: [PATCH 14/18] =?UTF-8?q?=E2=9C=85=20Add=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/NonceBitmap.t.sol | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/NonceBitmap.t.sol b/test/NonceBitmap.t.sol index f6c29653..f4743d4b 100644 --- a/test/NonceBitmap.t.sol +++ b/test/NonceBitmap.t.sol @@ -88,6 +88,14 @@ contract NonceBitmapTest is Bootstrap, ConditionalOrderSignature { assertFalse(canExec); } + function test_invalidateUnorderedNonces_Unauthorized() public { + vm.prank(BAD_ACTOR); + + vm.expectRevert(abi.encodeWithSelector(IEngine.Unauthorized.selector)); + + engine.invalidateUnorderedNonces(accountId, 0, type(uint256).max); + } + function test_invalidateUnorderedNonces_event() public { vm.expectEmit(true, true, true, true); emit UnorderedNonceInvalidation(accountId, 0, type(uint256).max); From b7391e31a7a6f6ab0a9ed7d1cc34ee9073702573 Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:50:03 -0500 Subject: [PATCH 15/18] =?UTF-8?q?=F0=9F=93=B8=20Update=20gas-snapshot/lcov?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 9 ++-- lcov.info | 142 +++++++++++++++++++++++++------------------------- 2 files changed, 76 insertions(+), 75 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 2871b775..20f51212 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -70,11 +70,12 @@ MathLibTest:test_abs256() (gas: 480) MathLibTest:test_fuzz_abs128(int128) (runs: 256, μ: 577, ~: 603) MathLibTest:test_fuzz_abs256(int256) (runs: 256, μ: 472, ~: 458) MathLibTest:test_isSameSign() (gas: 999) -NonceBitmapTest:test_fuzz_invalidateUnorderedNonces(uint256) (runs: 256, μ: 52920, ~: 52920) +NonceBitmapTest:test_fuzz_invalidateUnorderedNonces(uint256) (runs: 256, μ: 52942, ~: 52942) NonceBitmapTest:test_hasUnorderedNonceBeenUsed() (gas: 54209) -NonceBitmapTest:test_invalidateUnorderedNonces() (gas: 77434) -NonceBitmapTest:test_invalidateUnorderedNonces_Only_Owner_Delegate() (gas: 190646) -NonceBitmapTest:test_invalidateUnorderedNonces_event() (gas: 53592) +NonceBitmapTest:test_invalidateUnorderedNonces() (gas: 77468) +NonceBitmapTest:test_invalidateUnorderedNonces_Only_Owner_Delegate() (gas: 190668) +NonceBitmapTest:test_invalidateUnorderedNonces_Unauthorized() (gas: 30803) +NonceBitmapTest:test_invalidateUnorderedNonces_event() (gas: 53604) ReduceOnly:test_reduce_only() (gas: 432946) ReduceOnly:test_reduce_only_same_sign() (gas: 73941) ReduceOnly:test_reduce_only_truncate_size_down() (gas: 433054) diff --git a/lcov.info b/lcov.info index 8e6629ae..0f842c8f 100644 --- a/lcov.info +++ b/lcov.info @@ -1,44 +1,44 @@ TN: SF:script/Deploy.s.sol -FN:134,DeployOptimismGoerli_Synthetix.run -FNDA:0,DeployOptimismGoerli_Synthetix.run -DA:135,0 -DA:136,0 -DA:138,0 -DA:144,0 FN:98,DeployBaseGoerli_Andromeda.run FNDA:0,DeployBaseGoerli_Andromeda.run DA:99,0 DA:100,0 DA:102,0 DA:108,0 -FN:24,Setup.deploySystem -FNDA:4,Setup.deploySystem -DA:29,4 FN:41,DeployBase_Synthetix.run FNDA:0,DeployBase_Synthetix.run DA:42,0 DA:43,0 DA:45,0 DA:51,0 -FN:116,DeployOptimism_Synthetix.run -FNDA:0,DeployOptimism_Synthetix.run -DA:117,0 -DA:118,0 -DA:120,0 -DA:126,0 FN:59,DeployBaseGoerli_Synthetix.run FNDA:0,DeployBaseGoerli_Synthetix.run DA:60,0 DA:61,0 DA:63,0 DA:69,0 +FN:134,DeployOptimismGoerli_Synthetix.run +FNDA:0,DeployOptimismGoerli_Synthetix.run +DA:135,0 +DA:136,0 +DA:138,0 +DA:144,0 FN:80,DeployBaseGoerli_KwentaFork.run FNDA:0,DeployBaseGoerli_KwentaFork.run DA:81,0 DA:82,0 DA:84,0 DA:90,0 +FN:116,DeployOptimism_Synthetix.run +FNDA:0,DeployOptimism_Synthetix.run +DA:117,0 +DA:118,0 +DA:120,0 +DA:126,0 +FN:24,Setup.deploySystem +FNDA:4,Setup.deploySystem +DA:29,4 FNF:7 FNH:1 LF:25 @@ -50,7 +50,7 @@ TN: SF:src/Engine.sol FN:115,Engine.trustedForwarder FNDA:1,Engine.trustedForwarder -DA:116,1853 +DA:116,1854 FN:124,Engine.isAccountOwner FNDA:4,Engine.isAccountOwner DA:130,271 @@ -59,17 +59,17 @@ FN:135,Engine.isAccountDelegate FNDA:3,Engine.isAccountDelegate DA:141,3 FN:146,Engine._isAccountOwnerOrDelegate -FNDA:285,Engine._isAccountOwnerOrDelegate -DA:151,285 -DA:152,285 +FNDA:286,Engine._isAccountOwnerOrDelegate +DA:151,286 +DA:152,286 FN:162,Engine.depositEth FNDA:523,Engine.depositEth DA:165,523 -BRDA:165,0,0,240 -BRDA:165,0,1,283 -DA:166,240 -DA:169,283 -DA:171,283 +BRDA:165,0,0,231 +BRDA:165,0,1,292 +DA:166,231 +DA:169,292 +DA:171,292 FN:175,Engine.withdrawEth FNDA:261,Engine.withdrawEth DA:179,261 @@ -89,13 +89,13 @@ DA:202,272 BRDA:202,3,0,1 BRDA:202,3,1,271 FN:210,Engine.invalidateUnorderedNonces -FNDA:261,Engine.invalidateUnorderedNonces -DA:215,261 +FNDA:262,Engine.invalidateUnorderedNonces +DA:215,262 BRDA:215,4,0,261 -BRDA:215,4,1,- +BRDA:215,4,1,1 DA:221,261 DA:223,261 -DA:225,0 +DA:225,1 FN:230,Engine.hasUnorderedNonceBeenUsed FNDA:260,Engine.hasUnorderedNonceBeenUsed DA:236,280 @@ -269,9 +269,9 @@ DA:732,4 FNF:30 FNH:30 LF:108 -LH:106 +LH:107 BRF:50 -BRH:43 +BRH:44 end_of_record TN: SF:src/libraries/ConditionalOrderHashLib.sol @@ -432,42 +432,42 @@ end_of_record TN: SF:src/utils/TrustedForwarder.sol FN:30,TrustedForwarder.aggregate -FNDA:1441,TrustedForwarder.aggregate -DA:35,1441 -DA:36,1441 -DA:38,1441 -DA:39,1441 -DA:41,1441 -DA:43,1448 -DA:47,1448 +FNDA:1456,TrustedForwarder.aggregate +DA:35,1456 +DA:36,1456 +DA:38,1456 +DA:39,1456 +DA:41,1456 +DA:43,1463 +DA:47,1463 BRDA:47,0,0,1 -BRDA:47,0,1,1447 +BRDA:47,0,1,1462 DA:48,1 -DA:52,1447 -DA:57,1447 -DA:60,1447 -DA:67,1447 +DA:52,1462 +DA:57,1462 +DA:60,1462 +DA:67,1462 BRDA:67,1,0,1026 -BRDA:67,1,1,421 +BRDA:67,1,1,436 DA:68,1026 DA:69,1026 -DA:75,421 -DA:78,421 -DA:83,414 +DA:75,436 +DA:78,436 +DA:83,429 BRDA:83,2,0,2 -BRDA:83,2,1,412 +BRDA:83,2,1,427 DA:84,2 FN:91,TrustedForwarder._isTrustedByTarget -FNDA:1448,TrustedForwarder._isTrustedByTarget -DA:92,1448 -DA:93,1448 -DA:95,1448 -DA:96,1448 -DA:97,1448 -DA:105,1448 -DA:114,1448 -DA:115,1448 -DA:118,1448 +FNDA:1463,TrustedForwarder._isTrustedByTarget +DA:92,1463 +DA:93,1463 +DA:95,1463 +DA:96,1463 +DA:97,1463 +DA:105,1463 +DA:114,1463 +DA:115,1463 +DA:118,1463 FNF:2 FNH:2 LF:27 @@ -577,11 +577,6 @@ BRH:0 end_of_record TN: SF:test/utils/Bootstrap.sol -FN:98,BootstrapOptimism.init -FNDA:0,BootstrapOptimism.init -DA:102,0 -DA:108,0 -DA:114,0 FN:125,BootstrapOptimismGoerli.init FNDA:0,BootstrapOptimismGoerli.init DA:129,0 @@ -621,6 +616,11 @@ DA:85,0 DA:86,0 DA:91,0 DA:93,0 +FN:98,BootstrapOptimism.init +FNDA:0,BootstrapOptimism.init +DA:102,0 +DA:108,0 +DA:114,0 FNF:4 FNH:0 LF:36 @@ -712,6 +712,12 @@ BRH:0 end_of_record TN: SF:test/utils/mocks/EIP7412Mock.sol +FN:7,EIP7412Mock.fulfillOracleQuery +FNDA:1024,EIP7412Mock.fulfillOracleQuery +DA:8,1024 +BRDA:8,0,0,512 +BRDA:8,0,1,512 +DA:10,512 FN:15,EIP7412MockRefund.fulfillOracleQuery FNDA:512,EIP7412MockRefund.fulfillOracleQuery DA:16,512 @@ -721,12 +727,6 @@ DA:17,512 DA:18,512 BRDA:18,1,0,512 BRDA:18,1,1,- -FN:7,EIP7412Mock.fulfillOracleQuery -FNDA:1024,EIP7412Mock.fulfillOracleQuery -DA:8,1024 -BRDA:8,0,0,512 -BRDA:8,0,1,512 -DA:10,512 FN:23,EIP7412MockRevert.fulfillOracleQuery FNDA:512,EIP7412MockRevert.fulfillOracleQuery DA:24,512 @@ -759,8 +759,8 @@ DA:29,1 BRDA:29,1,0,1 BRDA:29,1,1,- FN:32,MockCalleeWithContext.lockEth -FNDA:162,MockCalleeWithContext.lockEth -DA:34,162 +FNDA:177,MockCalleeWithContext.lockEth +DA:34,177 FNF:6 FNH:4 LF:6 From 539cf3c2771a43288640cd107c555790e10ecef6 Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:57:22 -0500 Subject: [PATCH 16/18] =?UTF-8?q?=E2=9C=85=20Add=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/ConditionalOrder.t.sol | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/ConditionalOrder.t.sol b/test/ConditionalOrder.t.sol index 811afad3..9523b854 100644 --- a/test/ConditionalOrder.t.sol +++ b/test/ConditionalOrder.t.sol @@ -173,6 +173,42 @@ contract CanExecute is ConditionalOrderTest { assertFalse(canExec); } + + function test_canExecute_false_require_verify_condition_not_met() public { + bytes[] memory conditions = new bytes[](1); + conditions[0] = isTimestampAfter(block.timestamp + 100); // condition not met + + IEngine.OrderDetails memory orderDetails = IEngine.OrderDetails({ + marketId: SETH_PERPS_MARKET_ID, + accountId: accountId, + sizeDelta: SIZE_DELTA, + settlementStrategyId: SETTLEMENT_STRATEGY_ID, + acceptablePrice: ACCEPTABLE_PRICE, + isReduceOnly: false, + trackingCode: TRACKING_CODE, + referrer: REFERRER + }); + + IEngine.ConditionalOrder memory co = IEngine.ConditionalOrder({ + orderDetails: orderDetails, + signer: signer, + nonce: 0, + requireVerified: true, + trustedExecutor: address(this), + maxExecutorFee: type(uint256).max, + conditions: conditions + }); + + bytes memory signature = getConditionalOrderSignature({ + co: co, + privateKey: signerPrivateKey, + domainSeparator: engine.DOMAIN_SEPARATOR() + }); + + bool canExec = engine.canExecute(co, signature, ZERO_CO_FEE); + + assertFalse(canExec); + } } contract VerifySigner is ConditionalOrderTest { From 99ba169e1747b42f58e74e07f6c678fc0faeadb8 Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 12 Dec 2023 13:58:44 -0500 Subject: [PATCH 17/18] =?UTF-8?q?=F0=9F=93=B8=20Update=20gas-snapshot/lcov?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 3 +- lcov.info | 260 +++++++++++++++++++++++++------------------------- 2 files changed, 132 insertions(+), 131 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 20f51212..e20f58e7 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -23,9 +23,10 @@ Aggregate:test_aggregate_value_multiple() (gas: 51915) Aggregate:test_aggregate_value_single(uint256) (runs: 256, μ: 24828, ~: 29186) CanExecute:test_canExecute_false_insufficent_account_credit() (gas: 414818) CanExecute:test_canExecute_false_invalid_signature() (gas: 446729) -CanExecute:test_canExecute_false_invalid_signer() (gas: 441990) +CanExecute:test_canExecute_false_invalid_signer() (gas: 442013) CanExecute:test_canExecute_false_maxExecutorFee_exceeded() (gas: 397486) CanExecute:test_canExecute_false_nonce_used() (gas: 827209) +CanExecute:test_canExecute_false_require_verify_condition_not_met() (gas: 51501) CanExecute:test_canExecute_false_trusted_executor() (gas: 439497) CanExecute:test_canExecute_true() (gas: 439136) CommitOrder:test_commitOrder() (gas: 383166) diff --git a/lcov.info b/lcov.info index 0f842c8f..67610f3b 100644 --- a/lcov.info +++ b/lcov.info @@ -1,44 +1,44 @@ TN: SF:script/Deploy.s.sol -FN:98,DeployBaseGoerli_Andromeda.run -FNDA:0,DeployBaseGoerli_Andromeda.run -DA:99,0 -DA:100,0 -DA:102,0 -DA:108,0 -FN:41,DeployBase_Synthetix.run -FNDA:0,DeployBase_Synthetix.run -DA:42,0 -DA:43,0 -DA:45,0 -DA:51,0 -FN:59,DeployBaseGoerli_Synthetix.run -FNDA:0,DeployBaseGoerli_Synthetix.run -DA:60,0 -DA:61,0 -DA:63,0 -DA:69,0 +FN:116,DeployOptimism_Synthetix.run +FNDA:0,DeployOptimism_Synthetix.run +DA:117,0 +DA:118,0 +DA:120,0 +DA:126,0 FN:134,DeployOptimismGoerli_Synthetix.run FNDA:0,DeployOptimismGoerli_Synthetix.run DA:135,0 DA:136,0 DA:138,0 DA:144,0 +FN:24,Setup.deploySystem +FNDA:4,Setup.deploySystem +DA:29,4 +FN:41,DeployBase_Synthetix.run +FNDA:0,DeployBase_Synthetix.run +DA:42,0 +DA:43,0 +DA:45,0 +DA:51,0 FN:80,DeployBaseGoerli_KwentaFork.run FNDA:0,DeployBaseGoerli_KwentaFork.run DA:81,0 DA:82,0 DA:84,0 DA:90,0 -FN:116,DeployOptimism_Synthetix.run -FNDA:0,DeployOptimism_Synthetix.run -DA:117,0 -DA:118,0 -DA:120,0 -DA:126,0 -FN:24,Setup.deploySystem -FNDA:4,Setup.deploySystem -DA:29,4 +FN:98,DeployBaseGoerli_Andromeda.run +FNDA:0,DeployBaseGoerli_Andromeda.run +DA:99,0 +DA:100,0 +DA:102,0 +DA:108,0 +FN:59,DeployBaseGoerli_Synthetix.run +FNDA:0,DeployBaseGoerli_Synthetix.run +DA:60,0 +DA:61,0 +DA:63,0 +DA:69,0 FNF:7 FNH:1 LF:25 @@ -59,17 +59,17 @@ FN:135,Engine.isAccountDelegate FNDA:3,Engine.isAccountDelegate DA:141,3 FN:146,Engine._isAccountOwnerOrDelegate -FNDA:286,Engine._isAccountOwnerOrDelegate -DA:151,286 -DA:152,286 +FNDA:287,Engine._isAccountOwnerOrDelegate +DA:151,287 +DA:152,287 FN:162,Engine.depositEth FNDA:523,Engine.depositEth DA:165,523 -BRDA:165,0,0,231 -BRDA:165,0,1,292 -DA:166,231 -DA:169,292 -DA:171,292 +BRDA:165,0,0,232 +BRDA:165,0,1,291 +DA:166,232 +DA:169,291 +DA:171,291 FN:175,Engine.withdrawEth FNDA:261,Engine.withdrawEth DA:179,261 @@ -98,13 +98,13 @@ DA:223,261 DA:225,1 FN:230,Engine.hasUnorderedNonceBeenUsed FNDA:260,Engine.hasUnorderedNonceBeenUsed -DA:236,280 -DA:240,280 -DA:254,280 +DA:236,281 +DA:240,281 +DA:254,281 FN:264,Engine._bitmapPositions -FNDA:293,Engine._bitmapPositions -DA:271,293 -DA:275,293 +FNDA:294,Engine._bitmapPositions +DA:271,294 +DA:275,294 FN:281,Engine._useUnorderedNonce FNDA:13,Engine._useUnorderedNonce DA:282,13 @@ -174,28 +174,28 @@ DA:503,2 DA:508,10 DA:518,7 FN:526,Engine.canExecute -FNDA:9,Engine.canExecute -DA:532,24 +FNDA:10,Engine.canExecute +DA:532,25 BRDA:532,14,0,2 -BRDA:532,14,1,22 -DA:535,22 +BRDA:532,14,1,23 +DA:535,23 BRDA:535,15,0,2 -BRDA:535,15,1,20 -DA:538,20 +BRDA:535,15,1,21 +DA:538,21 BRDA:538,16,0,2 -BRDA:538,16,1,18 +BRDA:538,16,1,19 DA:539,2 -DA:543,18 +DA:543,19 BRDA:543,17,0,1 -BRDA:543,17,1,17 -DA:546,17 +BRDA:543,17,1,18 +DA:546,18 BRDA:546,18,0,1 -BRDA:546,18,1,16 -DA:549,16 -BRDA:549,19,0,- +BRDA:546,18,1,17 +DA:549,17 +BRDA:549,19,0,1 BRDA:549,19,1,- -DA:552,0 -BRDA:552,20,0,- +DA:552,1 +BRDA:552,20,0,1 BRDA:552,20,1,- DA:556,16 BRDA:556,21,0,1 @@ -203,22 +203,22 @@ BRDA:556,21,1,15 DA:559,15 FN:567,Engine.verifySigner FNDA:2,Engine.verifySigner -DA:573,20 +DA:573,21 FN:577,Engine.verifySignature FNDA:257,Engine.verifySignature -DA:581,274 +DA:581,275 FN:585,Engine.verifyConditions FNDA:4,Engine.verifyConditions -DA:591,4 -DA:592,4 +DA:591,5 +DA:592,5 BRDA:592,22,0,1 -BRDA:592,22,1,3 +BRDA:592,22,1,4 DA:593,1 -DA:596,3 -DA:597,13 -DA:598,13 -DA:601,13 -DA:606,13 +DA:596,4 +DA:597,14 +DA:598,14 +DA:601,14 +DA:606,14 DA:607,11 DA:608,9 DA:609,7 @@ -226,18 +226,18 @@ DA:610,5 DA:611,4 DA:612,3 DA:613,2 -BRDA:605,23,0,1 +BRDA:605,23,0,2 BRDA:605,23,1,11 -DA:616,12 -DA:619,12 -BRDA:619,24,0,1 +DA:616,13 +DA:619,13 +BRDA:619,24,0,2 BRDA:619,24,1,11 DA:622,11 DA:625,1 DA:629,1 FN:637,Engine.isTimestampAfter -FNDA:5,Engine.isTimestampAfter -DA:643,5 +FNDA:6,Engine.isTimestampAfter +DA:643,6 FN:647,Engine.isTimestampBefore FNDA:5,Engine.isTimestampBefore DA:653,5 @@ -269,9 +269,9 @@ DA:732,4 FNF:30 FNH:30 LF:108 -LH:107 +LH:108 BRF:50 -BRH:44 +BRH:46 end_of_record TN: SF:src/libraries/ConditionalOrderHashLib.sol @@ -378,20 +378,20 @@ FNDA:0,EIP712._domainNameAndVersion DA:74,0 DA:75,0 FN:80,EIP712.DOMAIN_SEPARATOR -FNDA:282,EIP712.DOMAIN_SEPARATOR -DA:81,282 -DA:82,282 +FNDA:283,EIP712.DOMAIN_SEPARATOR +DA:81,283 +DA:82,283 BRDA:82,0,0,- -BRDA:82,0,1,282 +BRDA:82,0,1,283 DA:83,0 FN:100,EIP712._hashTypedData -FNDA:274,EIP712._hashTypedData -DA:105,274 -DA:106,274 +FNDA:275,EIP712._hashTypedData +DA:105,275 +DA:106,275 BRDA:106,1,0,- -BRDA:106,1,1,274 +BRDA:106,1,1,275 DA:107,0 -DA:115,274 +DA:115,275 FN:127,EIP712.eip712Domain FNDA:0,EIP712.eip712Domain DA:140,0 @@ -406,10 +406,10 @@ DA:154,0 DA:155,0 DA:164,0 FN:169,EIP712._cachedDomainSeparatorInvalidated -FNDA:556,EIP712._cachedDomainSeparatorInvalidated -DA:174,556 -DA:175,556 -DA:178,556 +FNDA:558,EIP712._cachedDomainSeparatorInvalidated +DA:174,558 +DA:175,558 +DA:178,558 FNF:6 FNH:3 LF:21 @@ -432,42 +432,42 @@ end_of_record TN: SF:src/utils/TrustedForwarder.sol FN:30,TrustedForwarder.aggregate -FNDA:1456,TrustedForwarder.aggregate -DA:35,1456 -DA:36,1456 -DA:38,1456 -DA:39,1456 -DA:41,1456 -DA:43,1463 -DA:47,1463 +FNDA:1452,TrustedForwarder.aggregate +DA:35,1452 +DA:36,1452 +DA:38,1452 +DA:39,1452 +DA:41,1452 +DA:43,1459 +DA:47,1459 BRDA:47,0,0,1 -BRDA:47,0,1,1462 +BRDA:47,0,1,1458 DA:48,1 -DA:52,1462 -DA:57,1462 -DA:60,1462 -DA:67,1462 +DA:52,1458 +DA:57,1458 +DA:60,1458 +DA:67,1458 BRDA:67,1,0,1026 -BRDA:67,1,1,436 +BRDA:67,1,1,432 DA:68,1026 DA:69,1026 -DA:75,436 -DA:78,436 -DA:83,429 +DA:75,432 +DA:78,432 +DA:83,425 BRDA:83,2,0,2 -BRDA:83,2,1,427 +BRDA:83,2,1,423 DA:84,2 FN:91,TrustedForwarder._isTrustedByTarget -FNDA:1463,TrustedForwarder._isTrustedByTarget -DA:92,1463 -DA:93,1463 -DA:95,1463 -DA:96,1463 -DA:97,1463 -DA:105,1463 -DA:114,1463 -DA:115,1463 -DA:118,1463 +FNDA:1459,TrustedForwarder._isTrustedByTarget +DA:92,1459 +DA:93,1459 +DA:95,1459 +DA:96,1459 +DA:97,1459 +DA:105,1459 +DA:114,1459 +DA:115,1459 +DA:118,1459 FNF:2 FNH:2 LF:27 @@ -577,11 +577,6 @@ BRH:0 end_of_record TN: SF:test/utils/Bootstrap.sol -FN:125,BootstrapOptimismGoerli.init -FNDA:0,BootstrapOptimismGoerli.init -DA:129,0 -DA:135,0 -DA:141,0 FN:36,Bootstrap.initializeOptimismGoerli FNDA:0,Bootstrap.initializeOptimismGoerli DA:37,0 @@ -621,6 +616,11 @@ FNDA:0,BootstrapOptimism.init DA:102,0 DA:108,0 DA:114,0 +FN:125,BootstrapOptimismGoerli.init +FNDA:0,BootstrapOptimismGoerli.init +DA:129,0 +DA:135,0 +DA:141,0 FNF:4 FNH:0 LF:36 @@ -712,12 +712,6 @@ BRH:0 end_of_record TN: SF:test/utils/mocks/EIP7412Mock.sol -FN:7,EIP7412Mock.fulfillOracleQuery -FNDA:1024,EIP7412Mock.fulfillOracleQuery -DA:8,1024 -BRDA:8,0,0,512 -BRDA:8,0,1,512 -DA:10,512 FN:15,EIP7412MockRefund.fulfillOracleQuery FNDA:512,EIP7412MockRefund.fulfillOracleQuery DA:16,512 @@ -727,6 +721,12 @@ DA:17,512 DA:18,512 BRDA:18,1,0,512 BRDA:18,1,1,- +FN:7,EIP7412Mock.fulfillOracleQuery +FNDA:1024,EIP7412Mock.fulfillOracleQuery +DA:8,1024 +BRDA:8,0,0,512 +BRDA:8,0,1,512 +DA:10,512 FN:23,EIP7412MockRevert.fulfillOracleQuery FNDA:512,EIP7412MockRevert.fulfillOracleQuery DA:24,512 @@ -739,8 +739,6 @@ BRH:4 end_of_record TN: SF:test/utils/mocks/MockCallee.sol -FN:8,MockCallee.thisMethodSucceeds -FNDA:0,MockCallee.thisMethodSucceeds FN:16,MockCalleeWithContext.thisMethodSucceeds FNDA:2,MockCalleeWithContext.thisMethodSucceeds FN:18,MockCalleeWithContext.thisMethodReverts @@ -759,8 +757,10 @@ DA:29,1 BRDA:29,1,0,1 BRDA:29,1,1,- FN:32,MockCalleeWithContext.lockEth -FNDA:177,MockCalleeWithContext.lockEth -DA:34,177 +FNDA:173,MockCalleeWithContext.lockEth +DA:34,173 +FN:8,MockCallee.thisMethodSucceeds +FNDA:0,MockCallee.thisMethodSucceeds FNF:6 FNH:4 LF:6 From a4296da39613f9f678ccb73cd8bbc17437917818 Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Thu, 14 Dec 2023 14:44:53 -0500 Subject: [PATCH 18/18] =?UTF-8?q?=F0=9F=93=9A=20Update=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/interfaces/IEngine.sol | 92 +++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 35 deletions(-) diff --git a/src/interfaces/IEngine.sol b/src/interfaces/IEngine.sol index 36ebbd46..045d0889 100644 --- a/src/interfaces/IEngine.sol +++ b/src/interfaces/IEngine.sol @@ -3,14 +3,15 @@ pragma solidity 0.8.20; import {IPerpsMarketProxy} from "src/interfaces/synthetix/IPerpsMarketProxy.sol"; -/// @title Kwenta Smart Margin v3: Engine Interface +/// @title Kwenta Smart Margin v3: Engine Interface] +/// @notice Conditional Order -> "co" /// @author JaredBorders (jaredborders@pm.me) interface IEngine { /*////////////////////////////////////////////////////////////// TYPES //////////////////////////////////////////////////////////////*/ - /// @notice order details used to create an order on a perps market within a conditional order + /// @notice order details used to create an order on a perps market within a co struct OrderDetails { // order market id uint128 marketId; @@ -30,7 +31,7 @@ interface IEngine { address referrer; } - /// @notice conditional order + /// @notice co struct ConditionalOrder { // order details OrderDetails orderDetails; @@ -40,11 +41,11 @@ interface IEngine { uint256 nonce; // option to require all extra conditions to be verified on-chain bool requireVerified; - // address that can execute the order if requireVerified is false + // address that can execute the order *if* requireVerified is false address trustedExecutor; // max fee denominated in ETH that can be paid to the executor uint256 maxExecutorFee; - // array of extra conditions to be met + // array of extra conditions to be met on-chain *if* requireVerified is true bytes[] conditions; } @@ -102,10 +103,10 @@ interface IEngine { /// @param amount the amount of eth withdrawn event EthWithdraw(uint128 indexed accountId, uint256 amount); - /// @notice emitted when a conditional order is executed + /// @notice emitted when a co is executed /// @param order the order commited to the perps market - /// that was defined in the conditional order - /// @param executorFee the fee paid to the executor for executing the conditional order + /// that was defined in the co + /// @param executorFee the fee paid to the executor for executing the co event ConditionalOrderExecuted( IPerpsMarketProxy.Data order, uint256 synthetixFees, uint256 executorFee ); @@ -219,14 +220,14 @@ interface IEngine { /// Conditional Orders /// /// tldr: - /// Conditional Orders (co's) are signed objects that define an async order - /// and the conditions that must be met for the order to be executed. + /// co's are signed objects that define an async order + /// and several conditions that must be met for the order to be executed. /// /// deep dive: /// co's are composed of 8 main parts: /// 1. The async order details which are defined in the OrderDetails struct /// (the order that is being submitted to Synthetix perps v3 market) - /// 2. isReduceOnly flag which indicates if the order can only reduce + /// 2. isReduceOnly flag which indicates if the order can *only* reduce /// the position size and is also defined in the OrderDetails struct /// 3. The signer of the co which must be the account owner or delegate /// and is included in the ConditionalOrder struct. @@ -236,13 +237,18 @@ interface IEngine { /// The nonce is not specific to an address, but rather an account id. /// THIS DATA IS ALWAYS CHECKED ON-CHAIN /// 5. The requireVerified flag which is included in the ConditionalOrder struct. - /// If requireVerified is true, all conditions defined in the co must be satisfied on-chain. - /// If requireVerified is false, the co can ONLY be executed by the trustedExecutor. + /// If requireVerified is true, all conditions defined in the co must be satisfied *on-chain* + /// at the time of execution. + /// If requireVerified is false, the co can ONLY be executed by the trustedExecutor and the conditions + /// array is effectively unused (in the on-chain context). /// Notice that the conditions are not checked on-chain if requireVerified is false but are - /// expected to be checked off-chain by the trustedExecutor. This saves a significant amount gas. + /// expected to be checked off-chain by the trustedExecutor. This saves a significant amount gas + /// and allows the trusted executor to employ additional sophisticated methods of ensuring + /// best trade execution. /// 6. The trustedExecutor address which is included in the ConditionalOrder struct. /// The trustedExecutor is the address that can execute the co if requireVerified is false. - /// If requireVerified is true, the trustedExecutor is ignored/not used. + /// If requireVerified is true, the trustedExecutor is ignored/not used and + /// the conditions array becomes the source of verification imposed on-chain. /// 7. The maxExecutorFee which is included in the ConditionalOrder struct. /// The maxExecutorFee is the maximum fee that can be imposed by the address that /// successfully executes the co (trustedExecutor or not). This max fee is denominated in ETH and is @@ -255,6 +261,7 @@ interface IEngine { /// Conditions are stictly limited selectors defined in the Engine contract /// (ex: isTimestampBeforeSelector, isPriceAboveSelector, etc.) /// + /// /// co's are not creaed on-chain. They are composed and signed off-chain. The signature /// is then passed to the Engine contract along with the co. The Engine contract then /// verifies the signature along with many other "things" to determine if the co can be executed. @@ -272,7 +279,8 @@ interface IEngine { /// ELSE IF requireVerified is false, check if the msg.sender is the trustedExecutor /// /// All of these checks are carried out via a call to the Engine's canExecute function - /// that returns true or false. If canExecute returns true, the co can be executed. + /// that returns true or false. If canExecute returns true, the co can be executed assuming the context of + /// the check(s) is/are reliable. /// If canExecute returns false, the co cannot be executed. /// This function is expected to be used off-chain to determine if the co can be executed. /// It will be called within the Engine's execute function to determine if the co can be executed @@ -281,7 +289,7 @@ interface IEngine { /// /// note: It is recommended to attempt simulating the co execution prior to submission /// or employ some other sophisticated stratgey to mitigate the risk of submitting a co that - /// cannot be executed due to internal Synthetix v3 scenarios that are *unpredictable*. + /// cannot be executed due to internal Synthetix v3 scenarios/contexts that are *unpredictable*. /// /// The Engine contract does not store co's. It only stores the nonceBitmaps for each account. /// The Engine does hold and account for ETH credit and can modify the ETH credit of an account. @@ -299,13 +307,13 @@ interface IEngine { /// requires traders deposit ETH to the "protocol" prior to trading. This ETH can be /// multipurposed to pay for fees. This is the approach taken by the Engine contract. - /// @custom:docs for more in-depth documentation of conditional order mechanism, + /// @custom:docs for more in-depth documentation of co mechanism, /// please refer to https://github.com/Kwenta/smart-margin-v3/wiki/Conditional-Orders - /// @notice execute a conditional order - /// @param _co the conditional order - /// @param _signature the signature of the conditional order - /// @param _fee the fee paid to executor for the conditional order + /// @notice execute a co + /// @param _co the co + /// @param _signature the signature of the co + /// @param _fee the fee paid to executor for the co /// @return retOrder the order committed /// @return synthetixFees the fees paid for the order to Synthetix /// and *NOT* the fees paid to the executor @@ -317,12 +325,14 @@ interface IEngine { external returns (IPerpsMarketProxy.Data memory retOrder, uint256 synthetixFees); - /// @notice checks if the conditional order can be executed - /// @param _co the conditional order which details the order to be executed and the conditions to be met - /// @param _signature the signature of the conditional order - /// @param _fee the executor specified fee for the executing the conditional order - /// @dev if the fee is greater than the maxExecutorFee defined in the conditional order, + /// @notice checks if the co can be executed + /// @param _co the co which details the order to be executed and the conditions to be met + /// @param _signature the signature of the co + /// @param _fee the executor specified fee for the executing the co + /// @dev if the fee is greater than the maxExecutorFee defined in the co, /// or if the account lacks sufficient ETH credit to pay the fee, canExecute will return false + /// @custom:warning this function may return false-positive results in the case the underlying Synthetix Perps v3 + /// market is in a state that is not predictable (ex: unpredictable updates to the market's simulated fill price) /// @return true if the order can be executed, false otherwise function canExecute( ConditionalOrder calldata _co, @@ -330,30 +340,30 @@ interface IEngine { uint256 _fee ) external view returns (bool); - /// @notice verify the conditional order signer is the owner or delegate of the account - /// @param _co the conditional order + /// @notice verify the co signer is the owner or delegate of the account + /// @param _co the co /// @return true if the signer is the owner or delegate of the account function verifySigner(ConditionalOrder calldata _co) external view returns (bool); - /// @notice verify the signature of the conditional order - /// @param _co the conditional order - /// @param _signature the signature of the conditional order + /// @notice verify the signature of the co + /// @param _co the co + /// @param _signature the signature of the co /// @return true if the signature is valid function verifySignature( ConditionalOrder calldata _co, bytes calldata _signature ) external view returns (bool); - /// @notice verify array of conditions defined in the conditional order + /// @notice verify array of conditions defined in the co /// @dev - /// 1. all conditions are defined by the conditional order creator + /// 1. all conditions are defined by the co creator /// 2. conditions are encoded function selectors and parameters /// 3. each function defined in the condition contract must return a truthy value /// 4. internally, staticcall is used to protect against malicious conditions - /// @param _co the conditional order + /// @param _co the co /// @return true if all conditions are met function verifyConditions(ConditionalOrder calldata _co) external @@ -364,6 +374,18 @@ interface IEngine { CONDITIONS //////////////////////////////////////////////////////////////*/ + /// DISCLAIMER: + /// Take note that if a trusted party is authorized to execute a co, then the trader + /// does not actually need to specify any conditions. In a contrived example, the trader + /// could simply "tell" the trusted party to execute the co if the price of ETH is above/below some number. + /// The trusted party would then check the price of ETH (via whatever method deemed necessary) + /// and execute the co. + /// This is a very simple example, but it illustrates the flexibility of the co + /// along with the degree of trust that will be placed in the trusted party. + /// Finally, it is expected that despite the conditions array being unnecessary in *this* context, + /// it will likely still be used to provide additional context to the trusted party. + /// However, *again*, it is not required. + /// @notice determine if current timestamp is after the given timestamp /// @param _timestamp the timestamp to compare against /// @return true if current timestamp is after the given `_timestamp`, false otherwise