From af3ba7f5426b4bbcc51e6aa85a4a09ebf26a779a Mon Sep 17 00:00:00 2001 From: JonathanAmenechi <7217608+JonathanAmenechi@users.noreply.github.com> Date: Mon, 26 Sep 2022 17:19:35 -0400 Subject: [PATCH] fix: add maker and taker amounts to OrderFilled and OrdersMatched events, formatting --- foundry.toml | 15 ++++- src/exchange/BaseExchange.sol | 6 +- src/exchange/CTFExchange.sol | 26 ++++---- .../interfaces/IConditionalTokens.sol | 2 +- src/exchange/interfaces/IHashing.sol | 2 +- src/exchange/interfaces/ISignatures.sol | 2 +- src/exchange/interfaces/ITrading.sol | 8 +-- src/exchange/libraries/CalculatorHelper.sol | 10 +-- src/exchange/libraries/TransferHelper.sol | 4 +- src/exchange/mixins/AssetOperations.sol | 27 +++----- src/exchange/mixins/Assets.sol | 4 +- src/exchange/mixins/Auth.sol | 2 +- src/exchange/mixins/Fees.sol | 2 +- src/exchange/mixins/Hashing.sol | 6 +- src/exchange/mixins/NonceManager.sol | 6 +- src/exchange/mixins/Pausable.sol | 2 +- src/exchange/mixins/PolyFactoryHelper.sol | 4 +- src/exchange/mixins/Registry.sol | 14 ++-- src/exchange/mixins/Signatures.sol | 12 ++-- src/exchange/mixins/Trading.sol | 64 +++++++++---------- src/exchange/scripts/ExchangeDeployment.s.sol | 4 +- src/exchange/test/BaseExchangeTest.sol | 30 ++++----- src/exchange/test/CTFExchange.t.sol | 20 +++--- src/exchange/test/MatchOrders.t.sol | 36 ++++++----- .../test/libraries/CalculatorHelper.t.sol | 6 +- 25 files changed, 158 insertions(+), 156 deletions(-) diff --git a/foundry.toml b/foundry.toml index edaf162..34a9686 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,5 +1,18 @@ -profile = { default = { libs = ["node_modules", "lib"] } } [profile.default] +solc = "0.8.15" ffi = true gas_reports = ["*"] out = "out" +optimizer_runs = 1000000 + +# fuzz settings +[profile.default.fuzz] +runs = 256 +[profile.intense.fuzz] +runs = 10_000 + +[fmt] +line_length = 120 +tab_width = 4 +bracket_spacing = true +single_line_statement_blocks = "single" \ No newline at end of file diff --git a/src/exchange/BaseExchange.sol b/src/exchange/BaseExchange.sol index 8ea3384..64ea448 100644 --- a/src/exchange/BaseExchange.sol +++ b/src/exchange/BaseExchange.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {ERC1155Holder} from "openzeppelin-contracts/token/ERC1155/utils/ERC1155Holder.sol"; -import {ReentrancyGuard} from "common/ReentrancyGuard.sol"; +import { ERC1155Holder } from "openzeppelin-contracts/token/ERC1155/utils/ERC1155Holder.sol"; +import { ReentrancyGuard } from "common/ReentrancyGuard.sol"; -abstract contract BaseExchange is ERC1155Holder, ReentrancyGuard {} +abstract contract BaseExchange is ERC1155Holder, ReentrancyGuard { } diff --git a/src/exchange/CTFExchange.sol b/src/exchange/CTFExchange.sol index 67bb05d..aa9a00b 100644 --- a/src/exchange/CTFExchange.sol +++ b/src/exchange/CTFExchange.sol @@ -1,20 +1,20 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import {Auth} from "./mixins/Auth.sol"; -import {Fees} from "./mixins/Fees.sol"; -import {Assets} from "./mixins/Assets.sol"; -import {Hashing} from "./mixins/Hashing.sol"; -import {Trading} from "./mixins/Trading.sol"; -import {Registry} from "./mixins/Registry.sol"; -import {Pausable} from "./mixins/Pausable.sol"; -import {Signatures} from "./mixins/Signatures.sol"; -import {NonceManager} from "./mixins/NonceManager.sol"; -import {AssetOperations} from "./mixins/AssetOperations.sol"; +import { Auth } from "./mixins/Auth.sol"; +import { Fees } from "./mixins/Fees.sol"; +import { Assets } from "./mixins/Assets.sol"; +import { Hashing } from "./mixins/Hashing.sol"; +import { Trading } from "./mixins/Trading.sol"; +import { Registry } from "./mixins/Registry.sol"; +import { Pausable } from "./mixins/Pausable.sol"; +import { Signatures } from "./mixins/Signatures.sol"; +import { NonceManager } from "./mixins/NonceManager.sol"; +import { AssetOperations } from "./mixins/AssetOperations.sol"; -import {BaseExchange} from "./BaseExchange.sol"; +import { BaseExchange } from "./BaseExchange.sol"; -import {Order} from "./libraries/OrderStructs.sol"; +import { Order } from "./libraries/OrderStructs.sol"; /// @title CTF Exchange /// @notice Implements logic for trading CTF assets @@ -35,7 +35,7 @@ contract CTFExchange is constructor(address _collateral, address _ctf, address _proxyFactory, address _safeFactory) Assets(_collateral, _ctf) Signatures(_proxyFactory, _safeFactory) - {} + { } /*////////////////////////////////////////////////////////////// PAUSE diff --git a/src/exchange/interfaces/IConditionalTokens.sol b/src/exchange/interfaces/IConditionalTokens.sol index a86cdc8..e6fb225 100644 --- a/src/exchange/interfaces/IConditionalTokens.sol +++ b/src/exchange/interfaces/IConditionalTokens.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol"; +import { IERC20 } from "openzeppelin-contracts/token/ERC20/IERC20.sol"; /// @title IConditionalTokens /// @notice Interface for the Gnosis ConditionalTokensFramework: https://github.com/gnosis/conditional-tokens-contracts/blob/master/contracts/ConditionalTokens.sol diff --git a/src/exchange/interfaces/IHashing.sol b/src/exchange/interfaces/IHashing.sol index 6cd932b..87c1eba 100644 --- a/src/exchange/interfaces/IHashing.sol +++ b/src/exchange/interfaces/IHashing.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {Order} from "../libraries/OrderStructs.sol"; +import { Order } from "../libraries/OrderStructs.sol"; abstract contract IHashing { function hashOrder(Order memory order) public view virtual returns (bytes32); diff --git a/src/exchange/interfaces/ISignatures.sol b/src/exchange/interfaces/ISignatures.sol index a6b6dff..d4d4341 100644 --- a/src/exchange/interfaces/ISignatures.sol +++ b/src/exchange/interfaces/ISignatures.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {Order} from "../libraries/OrderStructs.sol"; +import { Order } from "../libraries/OrderStructs.sol"; interface ISignaturesEE { error InvalidSignature(); diff --git a/src/exchange/interfaces/ITrading.sol b/src/exchange/interfaces/ITrading.sol index 45a591e..b10a654 100644 --- a/src/exchange/interfaces/ITrading.sol +++ b/src/exchange/interfaces/ITrading.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {OrderStatus, Order} from "../libraries/OrderStructs.sol"; +import { OrderStatus, Order } from "../libraries/OrderStructs.sol"; interface ITradingEE { error NotOwner(); @@ -24,8 +24,8 @@ interface ITradingEE { address indexed taker, uint256 makerAssetId, uint256 takerAssetId, - uint256 filled, - uint256 remaining, + uint256 makerAmountFilled, + uint256 takerAmountFilled, uint256 fee ); @@ -40,4 +40,4 @@ interface ITradingEE { ); } -interface ITrading is ITradingEE {} +interface ITrading is ITradingEE { } diff --git a/src/exchange/libraries/CalculatorHelper.sol b/src/exchange/libraries/CalculatorHelper.sol index d847ad9..90c1b10 100644 --- a/src/exchange/libraries/CalculatorHelper.sol +++ b/src/exchange/libraries/CalculatorHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {Order, Side} from "../libraries/OrderStructs.sol"; +import { Order, Side } from "../libraries/OrderStructs.sol"; library CalculatorHelper { uint256 internal constant ONE = 10 ** 18; @@ -56,16 +56,12 @@ library CalculatorHelper { } function _calculatePrice(uint256 makerAmount, uint256 takerAmount, Side side) internal pure returns (uint256) { - if (side == Side.BUY) { - return takerAmount != 0 ? makerAmount * ONE / takerAmount : 0; - } + if (side == Side.BUY) return takerAmount != 0 ? makerAmount * ONE / takerAmount : 0; return makerAmount != 0 ? takerAmount * ONE / makerAmount : 0; } function isCrossing(Order memory a, Order memory b) internal pure returns (bool) { - if (a.takerAmount == 0 || b.takerAmount == 0) { - return true; - } + if (a.takerAmount == 0 || b.takerAmount == 0) return true; return _isCrossing(calculatePrice(a), calculatePrice(b), a.side, b.side); } diff --git a/src/exchange/libraries/TransferHelper.sol b/src/exchange/libraries/TransferHelper.sol index d8d5f98..9177469 100644 --- a/src/exchange/libraries/TransferHelper.sol +++ b/src/exchange/libraries/TransferHelper.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {IERC1155} from "openzeppelin-contracts/token/ERC1155/IERC1155.sol"; +import { IERC1155 } from "openzeppelin-contracts/token/ERC1155/IERC1155.sol"; -import {SafeTransferLib, ERC20} from "common/libraries/SafeTransferLib.sol"; +import { SafeTransferLib, ERC20 } from "common/libraries/SafeTransferLib.sol"; /// @title TransferHelper /// @notice Helper method to transfer tokens diff --git a/src/exchange/mixins/AssetOperations.sol b/src/exchange/mixins/AssetOperations.sol index e80be36..23fc6d3 100644 --- a/src/exchange/mixins/AssetOperations.sol +++ b/src/exchange/mixins/AssetOperations.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol"; -import {IERC1155} from "openzeppelin-contracts/token/ERC1155/IERC1155.sol"; +import { IERC20 } from "openzeppelin-contracts/token/ERC20/IERC20.sol"; +import { IERC1155 } from "openzeppelin-contracts/token/ERC1155/IERC1155.sol"; -import {IAssets} from "../interfaces/IAssets.sol"; -import {IAssetOperations} from "../interfaces/IAssetOperations.sol"; -import {IConditionalTokens} from "../interfaces/IConditionalTokens.sol"; +import { IAssets } from "../interfaces/IAssets.sol"; +import { IAssetOperations } from "../interfaces/IAssetOperations.sol"; +import { IConditionalTokens } from "../interfaces/IConditionalTokens.sol"; -import {TransferHelper} from "../libraries/TransferHelper.sol"; +import { TransferHelper } from "../libraries/TransferHelper.sol"; /// @title Asset Operations /// @notice Operations on the CTF and Collateral assets @@ -16,26 +16,19 @@ abstract contract AssetOperations is IAssetOperations, IAssets { bytes32 public constant parentCollectionId = bytes32(0); function _getBalance(uint256 tokenId) internal override returns (uint256) { - if (tokenId == 0) { - return IERC20(getCollateral()).balanceOf(address(this)); - } + if (tokenId == 0) return IERC20(getCollateral()).balanceOf(address(this)); return IERC1155(getCtf()).balanceOf(address(this), tokenId); } function _transfer(address from, address to, uint256 id, uint256 value) internal override { - if (id == 0) { - return _transferCollateral(from, to, value); - } + if (id == 0) return _transferCollateral(from, to, value); return _transferCTF(from, to, id, value); } function _transferCollateral(address from, address to, uint256 value) internal { address token = getCollateral(); - if (from == address(this)) { - TransferHelper._transferERC20(token, to, value); - } else { - TransferHelper._transferFromERC20(token, from, to, value); - } + if (from == address(this)) TransferHelper._transferERC20(token, to, value); + else TransferHelper._transferFromERC20(token, from, to, value); } function _transferCTF(address from, address to, uint256 id, uint256 value) internal { diff --git a/src/exchange/mixins/Assets.sol b/src/exchange/mixins/Assets.sol index fb51df9..b68a170 100644 --- a/src/exchange/mixins/Assets.sol +++ b/src/exchange/mixins/Assets.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol"; +import { IERC20 } from "openzeppelin-contracts/token/ERC20/IERC20.sol"; -import {IAssets} from "../interfaces/IAssets.sol"; +import { IAssets } from "../interfaces/IAssets.sol"; abstract contract Assets is IAssets { address internal immutable collateral; diff --git a/src/exchange/mixins/Auth.sol b/src/exchange/mixins/Auth.sol index b42b354..c43d2a1 100644 --- a/src/exchange/mixins/Auth.sol +++ b/src/exchange/mixins/Auth.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {IAuth} from "../interfaces/IAuth.sol"; +import { IAuth } from "../interfaces/IAuth.sol"; /// @title Auth /// @notice Provides admin and operator roles and access control modifiers diff --git a/src/exchange/mixins/Fees.sol b/src/exchange/mixins/Fees.sol index cff1aa7..217e8ef 100644 --- a/src/exchange/mixins/Fees.sol +++ b/src/exchange/mixins/Fees.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {IFees} from "../interfaces/IFees.sol"; +import { IFees } from "../interfaces/IFees.sol"; abstract contract Fees is IFees { /// @notice Maximum fee rate that can be signed into an Order diff --git a/src/exchange/mixins/Hashing.sol b/src/exchange/mixins/Hashing.sol index 1bf60d7..d64727e 100644 --- a/src/exchange/mixins/Hashing.sol +++ b/src/exchange/mixins/Hashing.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {EIP712} from "openzeppelin-contracts/utils/cryptography/draft-EIP712.sol"; +import { EIP712 } from "openzeppelin-contracts/utils/cryptography/draft-EIP712.sol"; -import {IHashing} from "../interfaces/IHashing.sol"; +import { IHashing } from "../interfaces/IHashing.sol"; -import {Order, ORDER_TYPEHASH} from "../libraries/OrderStructs.sol"; +import { Order, ORDER_TYPEHASH } from "../libraries/OrderStructs.sol"; abstract contract Hashing is EIP712, IHashing { bytes32 public immutable domainSeparator; diff --git a/src/exchange/mixins/NonceManager.sol b/src/exchange/mixins/NonceManager.sol index fc56bae..db1f260 100644 --- a/src/exchange/mixins/NonceManager.sol +++ b/src/exchange/mixins/NonceManager.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {INonceManager} from "../interfaces/INonceManager.sol"; +import { INonceManager } from "../interfaces/INonceManager.sol"; abstract contract NonceManager is INonceManager { mapping(address => uint256) public nonces; @@ -11,10 +11,10 @@ abstract contract NonceManager is INonceManager { } function updateNonce(uint256 val) internal { - nonces[msg.sender] = nonces[msg.sender] + val; + nonces[ msg.sender] = nonces[ msg.sender] + val; } function isValidNonce(address usr, uint256 nonce) public view override returns (bool) { - return nonces[usr] == nonce; + return nonces[ usr] == nonce; } } diff --git a/src/exchange/mixins/Pausable.sol b/src/exchange/mixins/Pausable.sol index 6103f35..4278712 100644 --- a/src/exchange/mixins/Pausable.sol +++ b/src/exchange/mixins/Pausable.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {IPausable} from "../interfaces/IPausable.sol"; +import { IPausable } from "../interfaces/IPausable.sol"; abstract contract Pausable is IPausable { bool public paused = false; diff --git a/src/exchange/mixins/PolyFactoryHelper.sol b/src/exchange/mixins/PolyFactoryHelper.sol index 42d34d9..b78d006 100644 --- a/src/exchange/mixins/PolyFactoryHelper.sol +++ b/src/exchange/mixins/PolyFactoryHelper.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {PolySafeLib} from "../libraries/PolySafeLib.sol"; -import {PolyProxyLib} from "../libraries/PolyProxyLib.sol"; +import { PolySafeLib } from "../libraries/PolySafeLib.sol"; +import { PolyProxyLib } from "../libraries/PolyProxyLib.sol"; interface IPolyProxyFactory { function getImplementation() external view returns (address); diff --git a/src/exchange/mixins/Registry.sol b/src/exchange/mixins/Registry.sol index ab8f420..82fa7df 100644 --- a/src/exchange/mixins/Registry.sol +++ b/src/exchange/mixins/Registry.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {IRegistry} from "../interfaces/IRegistry.sol"; +import { IRegistry } from "../interfaces/IRegistry.sol"; struct OutcomeToken { uint256 complement; @@ -15,14 +15,14 @@ abstract contract Registry is IRegistry { /// @notice Gets the conditionId from a tokenId /// @param token - The token function getConditionId(uint256 token) public view override returns (bytes32) { - return registry[token].conditionId; + return registry[ token].conditionId; } /// @notice Gets the complement of a tokenId /// @param token - The token function getComplement(uint256 token) public view override returns (uint256) { validateTokenId(token); - return registry[token].complement; + return registry[ token].complement; } /// @notice Validates the complement of a tokenId @@ -35,16 +35,16 @@ abstract contract Registry is IRegistry { /// @param tokenId - The tokenId function validateTokenId(uint256 tokenId) public view override { - if (registry[tokenId].complement == 0) revert InvalidTokenId(); + if (registry[ tokenId].complement == 0) revert InvalidTokenId(); } function _registerToken(uint256 token0, uint256 token1, bytes32 conditionId) internal { if (token0 == token1 || (token0 == 0 || token1 == 0)) revert InvalidTokenId(); - if (registry[token0].complement != 0 || registry[token1].complement != 0) revert AlreadyRegistered(); + if (registry[ token0].complement != 0 || registry[ token1].complement != 0) revert AlreadyRegistered(); - registry[token0] = OutcomeToken({complement: token1, conditionId: conditionId}); + registry[ token0] = OutcomeToken({complement: token1, conditionId: conditionId}); - registry[token1] = OutcomeToken({complement: token0, conditionId: conditionId}); + registry[ token1] = OutcomeToken({complement: token0, conditionId: conditionId}); emit TokenRegistered(token0, token1, conditionId); emit TokenRegistered(token1, token0, conditionId); diff --git a/src/exchange/mixins/Signatures.sol b/src/exchange/mixins/Signatures.sol index 7924111..4e30d19 100644 --- a/src/exchange/mixins/Signatures.sol +++ b/src/exchange/mixins/Signatures.sol @@ -1,19 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.10; -import {IERC1271} from "openzeppelin-contracts/interfaces/IERC1271.sol"; -import {ECDSA} from "openzeppelin-contracts/utils/cryptography/ECDSA.sol"; +import { IERC1271 } from "openzeppelin-contracts/interfaces/IERC1271.sol"; +import { ECDSA } from "openzeppelin-contracts/utils/cryptography/ECDSA.sol"; -import {SignatureType, Order} from "../libraries/OrderStructs.sol"; +import { SignatureType, Order } from "../libraries/OrderStructs.sol"; -import {ISignatures} from "../interfaces/ISignatures.sol"; +import { ISignatures } from "../interfaces/ISignatures.sol"; -import {PolyFactoryHelper} from "./PolyFactoryHelper.sol"; +import { PolyFactoryHelper } from "./PolyFactoryHelper.sol"; /// @title Signatures /// @notice Maintains logic that defines the various signature types and validates them abstract contract Signatures is ISignatures, PolyFactoryHelper { - constructor(address _proxyFactory, address _safeFactory) PolyFactoryHelper(_proxyFactory, _safeFactory) {} + constructor(address _proxyFactory, address _safeFactory) PolyFactoryHelper(_proxyFactory, _safeFactory) { } /// @notice Validates the signature of an order /// @param orderHash - The hash of the order diff --git a/src/exchange/mixins/Trading.sol b/src/exchange/mixins/Trading.sol index abcb13a..0a8354f 100644 --- a/src/exchange/mixins/Trading.sol +++ b/src/exchange/mixins/Trading.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {IFees} from "../interfaces/IFees.sol"; -import {IHashing} from "../interfaces/IHashing.sol"; -import {ITrading} from "../interfaces/ITrading.sol"; -import {IRegistry} from "../interfaces/IRegistry.sol"; -import {ISignatures} from "../interfaces/ISignatures.sol"; -import {INonceManager} from "../interfaces/INonceManager.sol"; -import {IAssetOperations} from "../interfaces/IAssetOperations.sol"; +import { IFees } from "../interfaces/IFees.sol"; +import { IHashing } from "../interfaces/IHashing.sol"; +import { ITrading } from "../interfaces/ITrading.sol"; +import { IRegistry } from "../interfaces/IRegistry.sol"; +import { ISignatures } from "../interfaces/ISignatures.sol"; +import { INonceManager } from "../interfaces/INonceManager.sol"; +import { IAssetOperations } from "../interfaces/IAssetOperations.sol"; -import {CalculatorHelper} from "../libraries/CalculatorHelper.sol"; -import {Order, Side, MatchType, OrderStatus} from "../libraries/OrderStructs.sol"; +import { CalculatorHelper } from "../libraries/CalculatorHelper.sol"; +import { Order, Side, MatchType, OrderStatus } from "../libraries/OrderStructs.sol"; /// @title Trading /// @notice Implements logic for trading CTF assets @@ -21,7 +21,7 @@ abstract contract Trading is IFees, ITrading, IHashing, IRegistry, ISignatures, /// @notice Gets the status of an order /// @param orderHash - The hash of the order function getOrderStatus(bytes32 orderHash) public view returns (OrderStatus memory) { - return orderStatus[orderHash]; + return orderStatus[ orderHash]; } /// @notice Validates an order @@ -44,7 +44,7 @@ abstract contract Trading is IFees, ITrading, IHashing, IRegistry, ISignatures, uint256 length = orders.length; uint256 i = 0; for (; i < length;) { - _cancelOrder(orders[i]); + _cancelOrder(orders[ i]); unchecked { ++i; } @@ -88,7 +88,7 @@ abstract contract Trading is IFees, ITrading, IHashing, IRegistry, ISignatures, /// @param to - The address to receive assets from filling the order function _fillOrder(Order memory order, uint256 fillAmount, address to) internal { uint256 making = fillAmount; - (uint256 taking, uint256 remaining, bytes32 orderHash) = _performOrderChecks(order, making); + (uint256 taking, bytes32 orderHash) = _performOrderChecks(order, making); uint256 fee = CalculatorHelper.calculateFee( order.feeRateBps, order.side == Side.BUY ? taking : making, order.makerAmount, order.takerAmount, order.side @@ -105,7 +105,7 @@ abstract contract Trading is IFees, ITrading, IHashing, IRegistry, ISignatures, // NOTE: Fees are "collected" by the Operator implicitly, // since the fee is deducted from the assets paid by the Operator - emit OrderFilled(orderHash, order.maker, msg.sender, makerAssetId, takerAssetId, making, remaining, fee); + emit OrderFilled(orderHash, order.maker, msg.sender, makerAssetId, takerAssetId, making, taking, fee); } /// @notice Fills a set of orders against the caller @@ -137,7 +137,7 @@ abstract contract Trading is IFees, ITrading, IHashing, IRegistry, ISignatures, ) internal { uint256 making = takerFillAmount; - (uint256 taking, uint256 remaining, bytes32 orderHash) = _performOrderChecks(takerOrder, making); + (uint256 taking, bytes32 orderHash) = _performOrderChecks(takerOrder, making); (uint256 makerAssetId, uint256 takerAssetId) = _deriveAssetIds(takerOrder); // Transfer takerOrder making amount from taker order to the Exchange @@ -159,15 +159,17 @@ abstract contract Trading is IFees, ITrading, IHashing, IRegistry, ISignatures, // Charge the fee to taker order maker, explicitly transferring the fee from the Exchange to the Operator _chargeFee(address(this), msg.sender, takerAssetId, fee); - emit OrderFilled(orderHash, takerOrder.maker, address(this), makerAssetId, takerAssetId, making, remaining, fee); + // Refund any leftover tokens pulled from the taker to the taker order + uint256 refund = _getBalance(makerAssetId); + if (refund > 0) _transfer(address(this), takerOrder.maker, makerAssetId, refund); + + emit OrderFilled( + orderHash, takerOrder.maker, address(this), makerAssetId, takerAssetId, making, taking, fee + ); emit OrdersMatched(orderHash, takerOrder.maker, makerAssetId, takerAssetId, making, taking); - // Refund any leftover tokens pulled from the taker to the taker order - uint256 refund = _getBalance(makerAssetId); - if (refund > 0) { - _transfer(address(this), takerOrder.maker, makerAssetId, refund); - } + } function _fillMakerOrders(Order memory takerOrder, Order[] memory makerOrders, uint256[] memory makerFillAmounts) @@ -194,7 +196,7 @@ abstract contract Trading is IFees, ITrading, IHashing, IRegistry, ISignatures, _validateTakerAndMaker(takerOrder, makerOrder, matchType); uint256 making = fillAmount; - (uint256 taking, uint256 remaining, bytes32 orderHash) = _performOrderChecks(makerOrder, making); + (uint256 taking, bytes32 orderHash) = _performOrderChecks(makerOrder, making); uint256 fee = CalculatorHelper.calculateFee( makerOrder.feeRateBps, makerOrder.side == Side.BUY ? taking : making, @@ -206,7 +208,9 @@ abstract contract Trading is IFees, ITrading, IHashing, IRegistry, ISignatures, _fillFacingExchange(making, taking, makerOrder.maker, makerAssetId, takerAssetId, matchType, fee); - emit OrderFilled(orderHash, makerOrder.maker, takerOrder.maker, makerAssetId, takerAssetId, making, remaining, fee); + emit OrderFilled( + orderHash, makerOrder.maker, takerOrder.maker, makerAssetId, takerAssetId, making, taking, fee + ); } /// @notice Performs common order computations and validation @@ -219,7 +223,7 @@ abstract contract Trading is IFees, ITrading, IHashing, IRegistry, ISignatures, /// @param making - The amount of the order being filled, in terms of maker amount function _performOrderChecks(Order memory order, uint256 making) internal - returns (uint256 takingAmount, uint256 remainingAmount, bytes32 orderHash) + returns (uint256 takingAmount, bytes32 orderHash) { _validateTaker(order.taker); @@ -232,7 +236,7 @@ abstract contract Trading is IFees, ITrading, IHashing, IRegistry, ISignatures, takingAmount = CalculatorHelper.calculateTakingAmount(making, order.makerAmount, order.takerAmount); // Update the order status in storage - remainingAmount = _updateOrderStatus(orderHash, order, making); + _updateOrderStatus(orderHash, order, making); } /// @notice Fills a maker order using the Exchange as the counterparty @@ -269,19 +273,13 @@ abstract contract Trading is IFees, ITrading, IHashing, IRegistry, ISignatures, } function _deriveMatchType(Order memory takerOrder, Order memory makerOrder) internal pure returns (MatchType) { - if (takerOrder.side == Side.BUY && makerOrder.side == Side.BUY) { - return MatchType.MINT; - } - if (takerOrder.side == Side.SELL && makerOrder.side == Side.SELL) { - return MatchType.MERGE; - } + if (takerOrder.side == Side.BUY && makerOrder.side == Side.BUY) return MatchType.MINT; + if (takerOrder.side == Side.SELL && makerOrder.side == Side.SELL) return MatchType.MERGE; return MatchType.COMPLEMENTARY; } function _deriveAssetIds(Order memory order) internal pure returns (uint256 makerAssetId, uint256 takerAssetId) { - if (order.side == Side.BUY) { - return (0, order.tokenId); - } + if (order.side == Side.BUY) return (0, order.tokenId); return (order.tokenId, 0); } diff --git a/src/exchange/scripts/ExchangeDeployment.s.sol b/src/exchange/scripts/ExchangeDeployment.s.sol index 8d2d23d..5972c21 100644 --- a/src/exchange/scripts/ExchangeDeployment.s.sol +++ b/src/exchange/scripts/ExchangeDeployment.s.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; -import {Script} from "forge-std/Script.sol"; -import {CTFExchange} from "exchange/CTFExchange.sol"; +import { Script } from "forge-std/Script.sol"; +import { CTFExchange } from "exchange/CTFExchange.sol"; /// @title ExchangeDeployment /// @notice Script to deploy the CTF Exchange diff --git a/src/exchange/test/BaseExchangeTest.sol b/src/exchange/test/BaseExchangeTest.sol index 5073e4d..15b10fb 100644 --- a/src/exchange/test/BaseExchangeTest.sol +++ b/src/exchange/test/BaseExchangeTest.sol @@ -1,25 +1,25 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {TestHelper} from "dev/TestHelper.sol"; -import {USDC} from "dev/mocks/USDC.sol"; -import {Deployer} from "dev/util/Deployer.sol"; +import { TestHelper } from "dev/TestHelper.sol"; +import { USDC } from "dev/mocks/USDC.sol"; +import { Deployer } from "dev/util/Deployer.sol"; -import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol"; -import {IERC1155} from "openzeppelin-contracts/token/ERC1155/IERC1155.sol"; +import { IERC20 } from "openzeppelin-contracts/token/ERC20/IERC20.sol"; +import { IERC1155 } from "openzeppelin-contracts/token/ERC1155/IERC1155.sol"; -import {CTFExchange} from "exchange/CTFExchange.sol"; -import {IAuthEE} from "exchange/interfaces/IAuth.sol"; -import {IFeesEE} from "exchange/interfaces/IFees.sol"; -import {ITradingEE} from "exchange/interfaces/ITrading.sol"; -import {IPausableEE} from "exchange/interfaces/IPausable.sol"; -import {IRegistryEE} from "exchange/interfaces/IRegistry.sol"; -import {ISignaturesEE} from "exchange/interfaces/ISignatures.sol"; +import { CTFExchange } from "exchange/CTFExchange.sol"; +import { IAuthEE } from "exchange/interfaces/IAuth.sol"; +import { IFeesEE } from "exchange/interfaces/IFees.sol"; +import { ITradingEE } from "exchange/interfaces/ITrading.sol"; +import { IPausableEE } from "exchange/interfaces/IPausable.sol"; +import { IRegistryEE } from "exchange/interfaces/IRegistry.sol"; +import { ISignaturesEE } from "exchange/interfaces/ISignatures.sol"; -import {IConditionalTokens} from "exchange/interfaces/IConditionalTokens.sol"; +import { IConditionalTokens } from "exchange/interfaces/IConditionalTokens.sol"; -import {CalculatorHelper} from "exchange/libraries/CalculatorHelper.sol"; -import {Order, Side, MatchType, OrderStatus, SignatureType} from "exchange/libraries/OrderStructs.sol"; +import { CalculatorHelper } from "exchange/libraries/CalculatorHelper.sol"; +import { Order, Side, MatchType, OrderStatus, SignatureType } from "exchange/libraries/OrderStructs.sol"; contract BaseExchangeTest is TestHelper, IAuthEE, IFeesEE, IRegistryEE, IPausableEE, ITradingEE, ISignaturesEE { mapping(address => mapping(address => mapping(uint256 => uint256))) private _checkpoints1155; diff --git a/src/exchange/test/CTFExchange.t.sol b/src/exchange/test/CTFExchange.t.sol index abdb154..b585d4c 100644 --- a/src/exchange/test/CTFExchange.t.sol +++ b/src/exchange/test/CTFExchange.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {BaseExchangeTest} from "exchange/test/BaseExchangeTest.sol"; -import {Order, Side, MatchType, OrderStatus, SignatureType} from "exchange/libraries/OrderStructs.sol"; +import { BaseExchangeTest } from "exchange/test/BaseExchangeTest.sol"; +import { Order, Side, MatchType, OrderStatus, SignatureType } from "exchange/libraries/OrderStructs.sol"; contract CTFExchangeTest is BaseExchangeTest { function testSetup() public { @@ -91,7 +91,7 @@ contract CTFExchangeTest is BaseExchangeTest { // Order can be filled after unpausing vm.prank(carla); exchange.fillOrder(order, 50_000_000); - emit OrderFilled(exchange.hashOrder(order), bob, carla, 0, yes, 50_000_000, 0, 0); + emit OrderFilled(exchange.hashOrder(order), bob, carla, 0, yes, 50_000_000, 100_000_000, 0); } function testRegisterToken(uint256 _token0, uint256 _token1, uint256 _conditionId) public { @@ -217,7 +217,7 @@ contract CTFExchangeTest is BaseExchangeTest { bytes32 orderHash = exchange.hashOrder(order); vm.expectEmit(true, true, true, true); - emit OrderFilled(orderHash, bob, carla, 0, yes, 25_000_000, 25_000_000, 0); + emit OrderFilled(orderHash, bob, carla, 0, yes, 25_000_000, 50_000_000, 0); // Checkpoint USDC balance for carla and Outcome token balance for bob checkpointCollateral(carla); @@ -275,7 +275,7 @@ contract CTFExchangeTest is BaseExchangeTest { uint256 expectedFee = calculateFee(100, 50_000_000, order.makerAmount, order.takerAmount, order.side); vm.expectEmit(true, true, true, true); - emit OrderFilled(orderHash, bob, carla, 0, yes, 25_000_000, 25_000_000, expectedFee); + emit OrderFilled(orderHash, bob, carla, 0, yes, 25_000_000, 50_000_000, expectedFee); vm.prank(carla); exchange.fillOrder(order, 25_000_000); @@ -303,7 +303,7 @@ contract CTFExchangeTest is BaseExchangeTest { uint256 expectedFee = calculateFee(feeRateBps, taking, order.makerAmount, order.takerAmount, order.side); vm.expectEmit(true, true, true, true); - emit OrderFilled(orderHash, bob, carla, 0, yes, fillAmount, remaining, expectedFee); + emit OrderFilled(orderHash, bob, carla, 0, yes, fillAmount, taking, expectedFee); checkpointCTF(bob, yes); checkpointCollateral(carla); @@ -337,7 +337,7 @@ contract CTFExchangeTest is BaseExchangeTest { // The taker specified operator will successfully fill the order vm.expectEmit(true, true, true, true); - emit OrderFilled(exchange.hashOrder(order), bob, carla, 0, yes, 50_000_000, 0, 0); + emit OrderFilled(exchange.hashOrder(order), bob, carla, 0, yes, 50_000_000, 100_000_000, 0); vm.prank(carla); exchange.fillOrder(order, 50_000_000); @@ -391,13 +391,13 @@ contract CTFExchangeTest is BaseExchangeTest { calculateFee(100, 100_000_000, yesSell.makerAmount, yesSell.takerAmount, yesSell.side); vm.expectEmit(true, true, true, true); - emit OrderFilled(exchange.hashOrder(yesBuy), bob, carla, 0, yes, 50_000_000, 0, expectedFeeYesBuy); + emit OrderFilled(exchange.hashOrder(yesBuy), bob, carla, 0, yes, 50_000_000, 100_000_000, expectedFeeYesBuy); vm.expectEmit(true, true, true, true); - emit OrderFilled(exchange.hashOrder(noBuy), bob, carla, 0, no, 50_000_000, 0, expectedFeeNoBuy); + emit OrderFilled(exchange.hashOrder(noBuy), bob, carla, 0, no, 50_000_000, 100_000_000, expectedFeeNoBuy); vm.expectEmit(true, true, true, true); - emit OrderFilled(exchange.hashOrder(yesSell), bob, carla, yes, 0, 100_000_000, 0, expectedFeeYesSell); + emit OrderFilled(exchange.hashOrder(yesSell), bob, carla, yes, 0, 100_000_000, 60_000_000, expectedFeeYesSell); vm.prank(carla); exchange.fillOrders(orders, amounts); diff --git a/src/exchange/test/MatchOrders.t.sol b/src/exchange/test/MatchOrders.t.sol index 8f02b6c..e2c5d21 100644 --- a/src/exchange/test/MatchOrders.t.sol +++ b/src/exchange/test/MatchOrders.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {BaseExchangeTest} from "exchange/test/BaseExchangeTest.sol"; +import { BaseExchangeTest } from "exchange/test/BaseExchangeTest.sol"; -import {Order, Side, MatchType, OrderStatus} from "exchange/libraries/OrderStructs.sol"; +import { Order, Side, MatchType, OrderStatus } from "exchange/libraries/OrderStructs.sol"; contract MatchOrdersTest is BaseExchangeTest { function setUp() public override { @@ -18,12 +18,12 @@ contract MatchOrdersTest is BaseExchangeTest { Order memory sellA = _createAndSignOrder(carlaPK, yes, 50_000_000, 25_000_000, Side.SELL); Order memory sellB = _createAndSignOrder(carlaPK, yes, 100_000_000, 50_000_000, Side.SELL); Order[] memory makerOrders = new Order[](2); - makerOrders[0] = sellA; - makerOrders[1] = sellB; + makerOrders[ 0] = sellA; + makerOrders[ 1] = sellB; uint256[] memory fillAmounts = new uint256[](2); - fillAmounts[0] = 50_000_000; - fillAmounts[1] = 70_000_000; + fillAmounts[ 0] = 50_000_000; + fillAmounts[ 1] = 70_000_000; checkpointCollateral(carla); checkpointCTF(bob, yes); @@ -31,15 +31,15 @@ contract MatchOrdersTest is BaseExchangeTest { // Check fill events // First maker order is filled completely vm.expectEmit(true, true, true, false); - emit OrderFilled(exchange.hashOrder(sellA), carla, bob, yes, 0, 50_000_000, 0, 0); + emit OrderFilled(exchange.hashOrder(sellA), carla, bob, yes, 0, 50_000_000, 25_000_000, 0); // Second maker order is partially filled vm.expectEmit(true, true, true, false); - emit OrderFilled(exchange.hashOrder(sellB), carla, bob, yes, 0, 70_000_000, 30_000_000, 0); + emit OrderFilled(exchange.hashOrder(sellB), carla, bob, yes, 0, 70_000_000, 35_000_000, 0); // The taker order is filled completely vm.expectEmit(true, true, true, false); - emit OrderFilled(exchange.hashOrder(buy), bob, address(exchange), 0, yes, 60_000_000, 0, 0); + emit OrderFilled(exchange.hashOrder(buy), bob, address(exchange), 0, yes, 60_000_000, 120_000_000, 0); vm.expectEmit(true, true, true, false); emit OrdersMatched(exchange.hashOrder(buy), bob, 0, yes, 60_000_000, 120_000_000); @@ -355,7 +355,7 @@ contract MatchOrdersTest is BaseExchangeTest { } vm.expectEmit(true, true, true, true); - emit OrderFilled(exchange.hashOrder(sell), carla, bob, yes, 0, 50_000_000, 50_000_000, expectedMakerFee); + emit OrderFilled(exchange.hashOrder(sell), carla, bob, yes, 0, 50_000_000, 25_000_000, expectedMakerFee); if (expectedMakerFee > 0) { vm.expectEmit(true, true, true, false); @@ -363,7 +363,9 @@ contract MatchOrdersTest is BaseExchangeTest { } vm.expectEmit(true, true, true, true); - emit OrderFilled(exchange.hashOrder(buy), bob, address(exchange), 0, yes, 25_000_000, 25_000_000, expectedTakerFee); + emit OrderFilled( + exchange.hashOrder(buy), bob, address(exchange), 0, yes, 25_000_000, 50_000_000, expectedTakerFee + ); // Match the orders exchange.matchOrders(buy, makerOrders, takerFillAmount, fillAmounts); @@ -402,7 +404,7 @@ contract MatchOrdersTest is BaseExchangeTest { calculateFee(makerFeeRate, takerFillAmount, buy.makerAmount, buy.takerAmount, buy.side); vm.expectEmit(true, true, true, true); - emit OrderFilled(exchange.hashOrder(buy), carla, bob, 0, yes, 60_000_000, 0, expectedMakerFee); + emit OrderFilled(exchange.hashOrder(buy), carla, bob, 0, yes, 60_000_000, 100_000_000, expectedMakerFee); if (expectedTakerFee > 0) { vm.expectEmit(true, true, true, true); @@ -410,7 +412,7 @@ contract MatchOrdersTest is BaseExchangeTest { } vm.expectEmit(true, true, true, true); - emit OrderFilled(exchange.hashOrder(sell), bob, address(exchange), yes, 0, 100_000_000, 0, expectedTakerFee); + emit OrderFilled(exchange.hashOrder(sell), bob, address(exchange), yes, 0, 100_000_000, 60_000_000, expectedTakerFee); vm.expectEmit(true, true, true, true); emit OrdersMatched(exchange.hashOrder(sell), bob, yes, 0, 100_000_000, 60_000_000); @@ -460,13 +462,13 @@ contract MatchOrdersTest is BaseExchangeTest { emit FeeCharged(admin, no, expectedMakerFee); vm.expectEmit(true, true, true, true); - emit OrderFilled(exchange.hashOrder(noBuy), carla, bob, 0, no, 50_000_000, 0, expectedMakerFee); + emit OrderFilled(exchange.hashOrder(noBuy), carla, bob, 0, no, 50_000_000, 100_000_000, expectedMakerFee); vm.expectEmit(true, true, true, true); emit FeeCharged(admin, yes, expectedTakerFee); vm.expectEmit(true, true, true, true); - emit OrderFilled(exchange.hashOrder(buy), bob, address(exchange), 0, yes, 50_000_000, 0, expectedTakerFee); + emit OrderFilled(exchange.hashOrder(buy), bob, address(exchange), 0, yes, 50_000_000, 100_000_000, expectedTakerFee); // Match the orders exchange.matchOrders(buy, makerOrders, takerFillAmount, fillAmounts); @@ -517,13 +519,13 @@ contract MatchOrdersTest is BaseExchangeTest { emit FeeCharged(admin, 0, expectedMakerFee); vm.expectEmit(true, true, true, true); - emit OrderFilled(exchange.hashOrder(noSell), carla, bob, no, 0, 100_000_000, 0, expectedMakerFee); + emit OrderFilled(exchange.hashOrder(noSell), carla, bob, no, 0, 100_000_000, 50_000_000, expectedMakerFee); vm.expectEmit(true, true, true, true); emit FeeCharged(admin, 0, expectedTakerFee); vm.expectEmit(true, true, true, true); - emit OrderFilled(exchange.hashOrder(yesSell), bob, address(exchange), yes, 0, 100_000_000, 0, expectedTakerFee); + emit OrderFilled(exchange.hashOrder(yesSell), bob, address(exchange), yes, 0, 100_000_000, 50_000_000, expectedTakerFee); // Match the orders exchange.matchOrders(yesSell, makerOrders, takerFillAmount, fillAmounts); diff --git a/src/exchange/test/libraries/CalculatorHelper.t.sol b/src/exchange/test/libraries/CalculatorHelper.t.sol index c2a41d1..38bf54c 100644 --- a/src/exchange/test/libraries/CalculatorHelper.t.sol +++ b/src/exchange/test/libraries/CalculatorHelper.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity <0.9.0; -import {Test} from "forge-std/Test.sol"; +import { Test } from "forge-std/Test.sol"; -import {CalculatorHelper} from "exchange/libraries/CalculatorHelper.sol"; -import {Side} from "exchange/libraries/OrderStructs.sol"; +import { CalculatorHelper } from "exchange/libraries/CalculatorHelper.sol"; +import { Side } from "exchange/libraries/OrderStructs.sol"; contract CalculatorHelperTest is Test { function testFuzzCalculateTakingAmount(uint64 making, uint128 makerAmount, uint128 takerAmount) public {