diff --git a/packages/contracts/evm-contracts/contracts/orderbook/IOrderbookDex.sol b/packages/contracts/evm-contracts/contracts/orderbook/IOrderbookDex.sol new file mode 100644 index 000000000..5b126fe8f --- /dev/null +++ b/packages/contracts/evm-contracts/contracts/orderbook/IOrderbookDex.sol @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; + +/// @notice Facilitates base-chain trading of an asset that is living on a different app-chain. +/// @dev Orders are identified by a unique incremental `orderId`. +interface IOrderbookDex is IERC1155Receiver { + struct Order { + /// @dev The asset's unique token identifier. + uint256 assetId; + /// @dev The amount of the asset that is available to be sold. + uint256 assetAmount; + /// @dev The price per one unit of asset. + uint256 pricePerAsset; + /// @dev The seller's address. + address payable seller; + } + + /// @param seller The seller's address. + /// @param orderId The order's unique identifier. + /// @param assetId The asset's unique token identifier. + /// @param assetAmount The amount of the asset that has been put for sale. + /// @param pricePerAsset The requested price per one unit of asset. + event OrderCreated( + address indexed seller, + uint256 indexed orderId, + uint256 indexed assetId, + uint256 assetAmount, + uint256 pricePerAsset + ); + + /// @param seller The seller's address. + /// @param orderId The order's unique identifier. + /// @param buyer The buyer's address. + /// @param assetAmount The amount of the asset that was traded. + /// @param pricePerAsset The price per one unit of asset that was paid. + event OrderFilled( + address indexed seller, + uint256 indexed orderId, + address indexed buyer, + uint256 assetAmount, + uint256 pricePerAsset + ); + + /// @param seller The seller's address. + /// @param id The order's unique identifier. + event OrderCancelled(address indexed seller, uint256 indexed id); + + /// @notice The address of the asset that is being traded in this DEX contract. + function asset() external view returns (address); + + /// @notice The `orderId` of the next sell order. + function currentOrderId() external view returns (uint256); + + /// @notice Returns the Order struct information about an order identified by the `orderId`. + function getOrder(uint256 orderId) external view returns (Order memory); + + /// @notice Creates a sell order for the `assetAmount` of `assetId` at `pricePerAsset`. + /// @dev The order information is saved in a mapping `orderId -> Order`, with `orderId` being a unique incremental identifier. + /// MUST transfer the `assetAmount` of `assetId` from the seller to the contract. + /// MUST emit `OrderCreated` event. + /// @return The unique identifier of the created order. + function createSellOrder( + uint256 assetId, + uint256 assetAmount, + uint256 pricePerAsset + ) external returns (uint256); + + /// @notice Creates a batch of sell orders for the `assetAmount` of `assetId` at `pricePerAsset`. + /// @dev This is a batched version of `createSellOrder` that simply iterates through the arrays to call said function. + /// @return The unique identifiers of the created orders. + function createBatchSellOrder( + uint256[] memory assetIds, + uint256[] memory assetAmounts, + uint256[] memory pricesPerAssets + ) external returns (uint256[] memory); + + /// @notice Consecutively fills an array of orders identified by the `orderId` of each order, + /// by providing an exact amount of ETH and requesting a specific minimum amount of asset to receive. + /// @dev Transfers portions of msg.value to the orders' sellers according to the price. + /// The sum of asset amounts of filled orders MUST be at least `minimumAsset`. + /// If msg.value is more than the sum of orders' prices, it MUST refund the excess back to `msg.sender`. + /// MUST decrease the `assetAmount` parameter for the specified order according to how much of it was filled, + /// and transfer that amount of the order's `assetId` to the buyer. + /// MUST emit `OrderFilled` event for each order accordingly. + function fillOrdersExactEth(uint256 minimumAsset, uint256[] memory orderIds) external payable; + + /// @notice Consecutively fills an array of orders identified by the `orderId` of each order, + /// by providing a possibly surplus amount of ETH and requesting an exact amount of asset to receive. + /// @dev Transfers portions of msg.value to the orders' sellers according to the price. + /// The sum of asset amounts of filled orders MUST be exactly `assetAmount`. Excess ETH MUST be returned back to `msg.sender`. + /// MUST decrease the `assetAmount` parameter for the specified order according to how much of it was filled, + /// and transfer that amount of the order's `assetId` to the buyer. + /// MUST emit `OrderFilled` event for each order accordingly. + /// If msg.value is more than the sum of orders' prices, it MUST refund the difference back to `msg.sender`. + function fillOrdersExactAsset(uint256 assetAmount, uint256[] memory orderIds) external payable; + + /// @notice Cancels the sell order identified by the `orderId`, transferring the order's assets back to the seller. + /// @dev MUST revert if the order's seller is not `msg.sender`. + /// MUST change the `assetAmount` parameter for the specified order to `0`. + /// MUST emit `OrderCancelled` event. + /// MUST transfer the `assetAmount` of `assetId` back to the seller. + function cancelSellOrder(uint256 orderId) external; + + /// @notice Cancels a batch of sell orders identified by the `orderIds`, transferring the orders' assets back to the seller. + /// @dev This is a batched version of `cancelSellOrder` that simply iterates through the array to call said function. + function cancelBatchSellOrder(uint256[] memory orderIds) external; +} diff --git a/packages/contracts/evm-contracts/contracts/orderbook/OrderbookDex.sol b/packages/contracts/evm-contracts/contracts/orderbook/OrderbookDex.sol new file mode 100644 index 000000000..35b687203 --- /dev/null +++ b/packages/contracts/evm-contracts/contracts/orderbook/OrderbookDex.sol @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +import {Address} from "@openzeppelin/contracts/utils/Address.sol"; +import {Arrays} from "@openzeppelin/contracts/utils/Arrays.sol"; +import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; + +import {IInverseProjected1155} from "../token/IInverseProjected1155.sol"; +import {IOrderbookDex} from "./IOrderbookDex.sol"; + +/// @notice Facilitates base-chain trading of an asset that is living on a different app-chain. +contract OrderbookDex is IOrderbookDex, ERC1155Holder, ReentrancyGuard { + using Address for address payable; + using Arrays for uint256[]; + + /// @inheritdoc IOrderbookDex + address public immutable override asset; + /// @inheritdoc IOrderbookDex + uint256 public override currentOrderId; + mapping(uint256 orderId => Order) internal orders; + + error OrderDoesNotExist(uint256 orderId); + error InsufficientEndAmount(uint256 expectedAmount, uint256 actualAmount); + error InvalidArrayLength(); + error InvalidInput(uint256 input); + error Unauthorized(address sender); + + constructor(address _asset) { + asset = _asset; + } + + /// @inheritdoc IOrderbookDex + function getOrder(uint256 orderId) public view virtual returns (Order memory) { + return orders[orderId]; + } + + /// @inheritdoc IOrderbookDex + function createSellOrder( + uint256 assetId, + uint256 assetAmount, + uint256 pricePerAsset + ) public virtual returns (uint256) { + if (assetAmount == 0 || pricePerAsset == 0) { + revert InvalidInput(0); + } + IInverseProjected1155(asset).safeTransferFrom( + msg.sender, + address(this), + assetId, + assetAmount, + bytes("") + ); + Order memory newOrder = Order({ + assetId: assetId, + assetAmount: assetAmount, + pricePerAsset: pricePerAsset, + seller: payable(msg.sender) + }); + uint256 orderId = currentOrderId; + orders[orderId] = newOrder; + emit OrderCreated(msg.sender, orderId, assetId, assetAmount, pricePerAsset); + ++currentOrderId; + return orderId; + } + + /// @inheritdoc IOrderbookDex + function createBatchSellOrder( + uint256[] memory assetIds, + uint256[] memory assetAmounts, + uint256[] memory pricesPerAssets + ) public virtual returns (uint256[] memory) { + if (assetIds.length != assetAmounts.length || assetIds.length != pricesPerAssets.length) { + revert InvalidArrayLength(); + } + uint256[] memory orderIds = new uint256[](assetIds.length); + for (uint256 i; i < assetIds.length; ) { + orderIds[i] = createSellOrder( + assetIds.unsafeMemoryAccess(i), + assetAmounts.unsafeMemoryAccess(i), + pricesPerAssets.unsafeMemoryAccess(i) + ); + unchecked { + ++i; + } + } + return orderIds; + } + + /// @inheritdoc IOrderbookDex + function fillOrdersExactEth( + uint256 minimumAsset, + uint256[] memory orderIds + ) public payable virtual nonReentrant { + uint256 length = orderIds.length; + uint256 remainingEth = msg.value; + uint256 totalAssetReceived; + for (uint256 i; i < length; ++i) { + uint256 orderId = orderIds.unsafeMemoryAccess(i); + Order storage order = orders[orderId]; + if (order.assetAmount == 0) { + continue; + } + uint256 assetsToBuy = remainingEth / order.pricePerAsset; + if (assetsToBuy == 0) { + continue; + } + if (assetsToBuy > order.assetAmount) { + assetsToBuy = order.assetAmount; + } + order.assetAmount -= assetsToBuy; + remainingEth -= assetsToBuy * order.pricePerAsset; + totalAssetReceived += assetsToBuy; + IInverseProjected1155(asset).safeTransferFrom( + address(this), + msg.sender, + order.assetId, + assetsToBuy, + bytes("") + ); + order.seller.sendValue(assetsToBuy * order.pricePerAsset); + emit OrderFilled(order.seller, orderId, msg.sender, assetsToBuy, order.pricePerAsset); + if (remainingEth == 0) { + break; + } + } + if (totalAssetReceived < minimumAsset) { + revert InsufficientEndAmount(minimumAsset, totalAssetReceived); + } + if (remainingEth > 0) { + payable(msg.sender).sendValue(remainingEth); + } + } + + /// @inheritdoc IOrderbookDex + function fillOrdersExactAsset( + uint256 assetAmount, + uint256[] memory orderIds + ) public payable virtual nonReentrant { + uint256 length = orderIds.length; + uint256 remainingAsset = assetAmount; + uint256 remainingEth = msg.value; + for (uint256 i; i < length; ++i) { + uint256 orderId = orderIds.unsafeMemoryAccess(i); + Order storage order = orders[orderId]; + if (order.assetAmount == 0) { + continue; + } + uint256 assetsToBuy = order.assetAmount; + if (assetsToBuy > remainingAsset) { + assetsToBuy = remainingAsset; + } + if (assetsToBuy == 0) { + continue; + } + order.assetAmount -= assetsToBuy; + remainingEth -= assetsToBuy * order.pricePerAsset; + remainingAsset -= assetsToBuy; + IInverseProjected1155(asset).safeTransferFrom( + address(this), + msg.sender, + order.assetId, + assetsToBuy, + bytes("") + ); + order.seller.sendValue(assetsToBuy * order.pricePerAsset); + emit OrderFilled(order.seller, orderId, msg.sender, assetsToBuy, order.pricePerAsset); + if (remainingAsset == 0) { + break; + } + } + if (remainingAsset > 0) { + revert InsufficientEndAmount(assetAmount, assetAmount - remainingAsset); + } + if (remainingEth > 0) { + payable(msg.sender).sendValue(remainingEth); + } + } + + /// @inheritdoc IOrderbookDex + function cancelSellOrder(uint256 orderId) public virtual { + Order storage order = orders[orderId]; + if (msg.sender != order.seller) { + revert Unauthorized(msg.sender); + } + uint256 assetAmount = order.assetAmount; + delete order.assetAmount; + IInverseProjected1155(asset).safeTransferFrom( + address(this), + msg.sender, + order.assetId, + assetAmount, + bytes("") + ); + emit OrderCancelled(msg.sender, orderId); + } + + /// @inheritdoc IOrderbookDex + function cancelBatchSellOrder(uint256[] memory orderIds) public virtual { + for (uint256 i; i < orderIds.length; ) { + cancelSellOrder(orderIds.unsafeMemoryAccess(i)); + unchecked { + ++i; + } + } + } + + /// @dev Returns true if this contract implements the interface defined by `interfaceId`. See EIP165. + function supportsInterface( + bytes4 interfaceId + ) public view virtual override(ERC1155Holder, IERC165) returns (bool) { + return + interfaceId == type(IOrderbookDex).interfaceId || super.supportsInterface(interfaceId); + } +} diff --git a/packages/contracts/evm-contracts/foundry.toml b/packages/contracts/evm-contracts/foundry.toml index 75d5992f6..013100149 100644 --- a/packages/contracts/evm-contracts/foundry.toml +++ b/packages/contracts/evm-contracts/foundry.toml @@ -2,7 +2,7 @@ src = 'contracts' # the source directory test = 'test' # the test directory out = 'artifacts/forge' # the output directory (for artifacts) -libs = ['test-lib'] # a list of library directories +libs = ['test-lib'] # a list of library directories remappings = [ # a list of remappings '@openzeppelin/=../../../node_modules/@openzeppelin/', ] @@ -31,3 +31,5 @@ evm_version = 'berlin' # the evm version (by hardfork name) #block_coinbase = '0x0000000000000000000000000000000000000000' # the address of `block.coinbase` in tests #block_timestamp = 0 # the value of `block.timestamp` in tests #block_difficulty = 0 # the value of `block.difficulty` in tests +[invariant] +fail_on_revert = true \ No newline at end of file diff --git a/packages/contracts/evm-contracts/test-lib/StdInvariant.sol b/packages/contracts/evm-contracts/test-lib/StdInvariant.sol new file mode 100644 index 000000000..124a8666b --- /dev/null +++ b/packages/contracts/evm-contracts/test-lib/StdInvariant.sol @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +pragma experimental ABIEncoderV2; + +abstract contract StdInvariant { + struct FuzzSelector { + address addr; + bytes4[] selectors; + } + + address[] private _excludedContracts; + address[] private _excludedSenders; + address[] private _targetedContracts; + address[] private _targetedSenders; + + string[] private _excludedArtifacts; + string[] private _targetedArtifacts; + + FuzzSelector[] private _targetedArtifactSelectors; + FuzzSelector[] private _targetedSelectors; + + // Functions for users: + // These are intended to be called in tests. + + function excludeContract(address newExcludedContract_) internal { + _excludedContracts.push(newExcludedContract_); + } + + function excludeSender(address newExcludedSender_) internal { + _excludedSenders.push(newExcludedSender_); + } + + function excludeArtifact(string memory newExcludedArtifact_) internal { + _excludedArtifacts.push(newExcludedArtifact_); + } + + function targetArtifact(string memory newTargetedArtifact_) internal { + _targetedArtifacts.push(newTargetedArtifact_); + } + + function targetArtifactSelector(FuzzSelector memory newTargetedArtifactSelector_) internal { + _targetedArtifactSelectors.push(newTargetedArtifactSelector_); + } + + function targetContract(address newTargetedContract_) internal { + _targetedContracts.push(newTargetedContract_); + } + + function targetSelector(FuzzSelector memory newTargetedSelector_) internal { + _targetedSelectors.push(newTargetedSelector_); + } + + function targetSender(address newTargetedSender_) internal { + _targetedSenders.push(newTargetedSender_); + } + + // Functions for forge: + // These are called by forge to run invariant tests and don't need to be called in tests. + + function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) { + excludedArtifacts_ = _excludedArtifacts; + } + + function excludeContracts() public view returns (address[] memory excludedContracts_) { + excludedContracts_ = _excludedContracts; + } + + function excludeSenders() public view returns (address[] memory excludedSenders_) { + excludedSenders_ = _excludedSenders; + } + + function targetArtifacts() public view returns (string[] memory targetedArtifacts_) { + targetedArtifacts_ = _targetedArtifacts; + } + + function targetArtifactSelectors() + public + view + returns (FuzzSelector[] memory targetedArtifactSelectors_) + { + targetedArtifactSelectors_ = _targetedArtifactSelectors; + } + + function targetContracts() public view returns (address[] memory targetedContracts_) { + targetedContracts_ = _targetedContracts; + } + + function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) { + targetedSelectors_ = _targetedSelectors; + } + + function targetSenders() public view returns (address[] memory targetedSenders_) { + targetedSenders_ = _targetedSenders; + } +} diff --git a/packages/contracts/evm-contracts/test-lib/cheatcodes.sol b/packages/contracts/evm-contracts/test-lib/cheatcodes.sol index 830247b82..6ab18c355 100644 --- a/packages/contracts/evm-contracts/test-lib/cheatcodes.sol +++ b/packages/contracts/evm-contracts/test-lib/cheatcodes.sol @@ -52,6 +52,8 @@ interface CheatCodes { function expectRevert(bytes4) external; + function expectRevert() external; + // Record all storage reads and writes function record() external; @@ -81,4 +83,7 @@ interface CheatCodes { // Labels an address in call traces function label(address, string calldata) external; + + // If the condition is false, discard this run's fuzz inputs and generate new ones. + function assume(bool condition) external pure; } diff --git a/packages/contracts/evm-contracts/test-lib/console.sol b/packages/contracts/evm-contracts/test-lib/console.sol index a7a6dfdbf..05f562833 100644 --- a/packages/contracts/evm-contracts/test-lib/console.sol +++ b/packages/contracts/evm-contracts/test-lib/console.sol @@ -1,861 +1,1010 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.4.22 <0.9.0; -// source: https://github.com/gakonst/foundry/blob/bf845eb2144bc99352b7d9f77c3f6cdfe801f826/evm-adapters/testdata/console.sol -// date: 2022-03-03 - +/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should +/// use `int256` and `uint256`. This modified version fixes that. This version is recommended +/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in +/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`. +/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178 library console { address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); - function _sendLogPayload(bytes memory payload) private view { + function _castLogPayloadViewToPure( + function(bytes memory) internal view fnIn + ) internal pure returns (function(bytes memory) internal pure fnOut) { + assembly { + fnOut := fnIn + } + } + + function _sendLogPayload(bytes memory payload) internal pure { + _castLogPayloadViewToPure(_sendLogPayloadView)(payload); + } + + function _sendLogPayloadView(bytes memory payload) private view { uint256 payloadLength = payload.length; address consoleAddress = CONSOLE_ADDRESS; + /// @solidity memory-safe-assembly assembly { let payloadStart := add(payload, 32) let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) } } - function log() internal view { + function log() internal pure { _sendLogPayload(abi.encodeWithSignature("log()")); } - function logInt(int256 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(int)", p0)); + function logInt(int256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); } - function logUint(uint256 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); + function logUint(uint256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); } - function logString(string memory p0) internal view { + function logString(string memory p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } - function logBool(bool p0) internal view { + function logBool(bool p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } - function logAddress(address p0) internal view { + function logAddress(address p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } - function logBytes(bytes memory p0) internal view { + function logBytes(bytes memory p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); } - function logBytes1(bytes1 p0) internal view { + function logBytes1(bytes1 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); } - function logBytes2(bytes2 p0) internal view { + function logBytes2(bytes2 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); } - function logBytes3(bytes3 p0) internal view { + function logBytes3(bytes3 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); } - function logBytes4(bytes4 p0) internal view { + function logBytes4(bytes4 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); } - function logBytes5(bytes5 p0) internal view { + function logBytes5(bytes5 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); } - function logBytes6(bytes6 p0) internal view { + function logBytes6(bytes6 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); } - function logBytes7(bytes7 p0) internal view { + function logBytes7(bytes7 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); } - function logBytes8(bytes8 p0) internal view { + function logBytes8(bytes8 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); } - function logBytes9(bytes9 p0) internal view { + function logBytes9(bytes9 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); } - function logBytes10(bytes10 p0) internal view { + function logBytes10(bytes10 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); } - function logBytes11(bytes11 p0) internal view { + function logBytes11(bytes11 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); } - function logBytes12(bytes12 p0) internal view { + function logBytes12(bytes12 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); } - function logBytes13(bytes13 p0) internal view { + function logBytes13(bytes13 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); } - function logBytes14(bytes14 p0) internal view { + function logBytes14(bytes14 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); } - function logBytes15(bytes15 p0) internal view { + function logBytes15(bytes15 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); } - function logBytes16(bytes16 p0) internal view { + function logBytes16(bytes16 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); } - function logBytes17(bytes17 p0) internal view { + function logBytes17(bytes17 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); } - function logBytes18(bytes18 p0) internal view { + function logBytes18(bytes18 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); } - function logBytes19(bytes19 p0) internal view { + function logBytes19(bytes19 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); } - function logBytes20(bytes20 p0) internal view { + function logBytes20(bytes20 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); } - function logBytes21(bytes21 p0) internal view { + function logBytes21(bytes21 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); } - function logBytes22(bytes22 p0) internal view { + function logBytes22(bytes22 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); } - function logBytes23(bytes23 p0) internal view { + function logBytes23(bytes23 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); } - function logBytes24(bytes24 p0) internal view { + function logBytes24(bytes24 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); } - function logBytes25(bytes25 p0) internal view { + function logBytes25(bytes25 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); } - function logBytes26(bytes26 p0) internal view { + function logBytes26(bytes26 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); } - function logBytes27(bytes27 p0) internal view { + function logBytes27(bytes27 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); } - function logBytes28(bytes28 p0) internal view { + function logBytes28(bytes28 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); } - function logBytes29(bytes29 p0) internal view { + function logBytes29(bytes29 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); } - function logBytes30(bytes30 p0) internal view { + function logBytes30(bytes30 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); } - function logBytes31(bytes31 p0) internal view { + function logBytes31(bytes31 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); } - function logBytes32(bytes32 p0) internal view { + function logBytes32(bytes32 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); } - function log(uint256 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); + function log(uint256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); } - function log(string memory p0) internal view { + function log(int256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); + } + + function log(string memory p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } - function log(bool p0) internal view { + function log(bool p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } - function log(address p0) internal view { + function log(address p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } - function log(uint256 p0, uint256 p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1)); + function log(uint256 p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1)); + } + + function log(uint256 p0, string memory p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1)); } - function log(uint256 p0, string memory p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1)); + function log(uint256 p0, bool p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1)); } - function log(uint256 p0, bool p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1)); + function log(uint256 p0, address p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1)); } - function log(uint256 p0, address p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1)); + function log(string memory p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); } - function log(string memory p0, uint256 p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1)); + function log(string memory p0, int256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1)); } - function log(string memory p0, string memory p1) internal view { + function log(string memory p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); } - function log(string memory p0, bool p1) internal view { + function log(string memory p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); } - function log(string memory p0, address p1) internal view { + function log(string memory p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); } - function log(bool p0, uint256 p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1)); + function log(bool p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1)); } - function log(bool p0, string memory p1) internal view { + function log(bool p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); } - function log(bool p0, bool p1) internal view { + function log(bool p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); } - function log(bool p0, address p1) internal view { + function log(bool p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); } - function log(address p0, uint256 p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1)); + function log(address p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1)); } - function log(address p0, string memory p1) internal view { + function log(address p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); } - function log(address p0, bool p1) internal view { + function log(address p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); } - function log(address p0, address p1) internal view { + function log(address p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); } - function log(uint256 p0, uint256 p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2)); + function log(uint256 p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2)); } - function log(uint256 p0, uint256 p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2)); + function log(uint256 p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2)); } - function log(uint256 p0, uint256 p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2)); + function log(uint256 p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2)); } - function log(uint256 p0, uint256 p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2)); + function log(uint256 p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2)); } - function log(uint256 p0, string memory p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2)); + function log(uint256 p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2)); } - function log(uint256 p0, string memory p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2)); + function log(uint256 p0, string memory p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2)); } - function log(uint256 p0, string memory p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2)); + function log(uint256 p0, string memory p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2)); } - function log(uint256 p0, string memory p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2)); + function log(uint256 p0, string memory p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2)); } - function log(uint256 p0, bool p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2)); + function log(uint256 p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2)); } - function log(uint256 p0, bool p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2)); + function log(uint256 p0, bool p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2)); } - function log(uint256 p0, bool p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2)); + function log(uint256 p0, bool p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2)); } - function log(uint256 p0, bool p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2)); + function log(uint256 p0, bool p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2)); } - function log(uint256 p0, address p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2)); + function log(uint256 p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2)); } - function log(uint256 p0, address p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2)); + function log(uint256 p0, address p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2)); } - function log(uint256 p0, address p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2)); + function log(uint256 p0, address p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2)); } - function log(uint256 p0, address p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2)); + function log(uint256 p0, address p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2)); } - function log(string memory p0, uint256 p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2)); + function log(string memory p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2)); } - function log(string memory p0, uint256 p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2)); + function log(string memory p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2)); } - function log(string memory p0, uint256 p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2)); + function log(string memory p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2)); } - function log(string memory p0, uint256 p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2)); + function log(string memory p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2)); } - function log(string memory p0, string memory p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2)); + function log(string memory p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2)); } - function log(string memory p0, string memory p1, string memory p2) internal view { + function log(string memory p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); } - function log(string memory p0, string memory p1, bool p2) internal view { + function log(string memory p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); } - function log(string memory p0, string memory p1, address p2) internal view { + function log(string memory p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); } - function log(string memory p0, bool p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2)); + function log(string memory p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2)); } - function log(string memory p0, bool p1, string memory p2) internal view { + function log(string memory p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); } - function log(string memory p0, bool p1, bool p2) internal view { + function log(string memory p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); } - function log(string memory p0, bool p1, address p2) internal view { + function log(string memory p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); } - function log(string memory p0, address p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2)); + function log(string memory p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2)); } - function log(string memory p0, address p1, string memory p2) internal view { + function log(string memory p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); } - function log(string memory p0, address p1, bool p2) internal view { + function log(string memory p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); } - function log(string memory p0, address p1, address p2) internal view { + function log(string memory p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); } - function log(bool p0, uint256 p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2)); + function log(bool p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2)); } - function log(bool p0, uint256 p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2)); + function log(bool p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2)); } - function log(bool p0, uint256 p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2)); + function log(bool p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2)); } - function log(bool p0, uint256 p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2)); + function log(bool p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2)); } - function log(bool p0, string memory p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2)); + function log(bool p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2)); } - function log(bool p0, string memory p1, string memory p2) internal view { + function log(bool p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); } - function log(bool p0, string memory p1, bool p2) internal view { + function log(bool p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); } - function log(bool p0, string memory p1, address p2) internal view { + function log(bool p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); } - function log(bool p0, bool p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2)); + function log(bool p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2)); } - function log(bool p0, bool p1, string memory p2) internal view { + function log(bool p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); } - function log(bool p0, bool p1, bool p2) internal view { + function log(bool p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); } - function log(bool p0, bool p1, address p2) internal view { + function log(bool p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); } - function log(bool p0, address p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2)); + function log(bool p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2)); } - function log(bool p0, address p1, string memory p2) internal view { + function log(bool p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); } - function log(bool p0, address p1, bool p2) internal view { + function log(bool p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); } - function log(bool p0, address p1, address p2) internal view { + function log(bool p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); } - function log(address p0, uint256 p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2)); + function log(address p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2)); } - function log(address p0, uint256 p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2)); + function log(address p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2)); } - function log(address p0, uint256 p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2)); + function log(address p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2)); } - function log(address p0, uint256 p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2)); + function log(address p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2)); } - function log(address p0, string memory p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2)); + function log(address p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2)); } - function log(address p0, string memory p1, string memory p2) internal view { + function log(address p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); } - function log(address p0, string memory p1, bool p2) internal view { + function log(address p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); } - function log(address p0, string memory p1, address p2) internal view { + function log(address p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); } - function log(address p0, bool p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2)); + function log(address p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2)); } - function log(address p0, bool p1, string memory p2) internal view { + function log(address p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); } - function log(address p0, bool p1, bool p2) internal view { + function log(address p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); } - function log(address p0, bool p1, address p2) internal view { + function log(address p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); } - function log(address p0, address p1, uint256 p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2)); + function log(address p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2)); } - function log(address p0, address p1, string memory p2) internal view { + function log(address p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); } - function log(address p0, address p1, bool p2) internal view { + function log(address p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); } - function log(address p0, address p1, address p2) internal view { + function log(address p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); } - function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3)); } - function log(uint256 p0, uint256 p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3) + ); } - function log(uint256 p0, uint256 p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3) + ); } - function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3) + ); } - function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3) + ); } - function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3) + ); } - function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3) + ); } - function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3)); } - function log(uint256 p0, string memory p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3) + ); } - function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3)); } - function log(uint256 p0, string memory p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3)); } - function log(uint256 p0, string memory p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, bool p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3) + ); } - function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, string memory p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3) + ); } - function log(uint256 p0, string memory p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, address p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3) + ); } - function log(uint256 p0, string memory p1, address p2, address p3) internal view { + function log(uint256 p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3) + abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3) ); } - function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3) + ); } - function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3)); } - function log(uint256 p0, bool p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3) + ); } - function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3)); } - function log(uint256 p0, bool p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3)); } - function log(uint256 p0, bool p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, string memory p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3) + ); } - function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3)); } - function log(uint256 p0, bool p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3)); } - function log(uint256 p0, bool p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3)); } - function log(uint256 p0, bool p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3)); } - function log(uint256 p0, bool p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, bool p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, address p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3) + ); } - function log(uint256 p0, bool p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3)); } - function log(uint256 p0, bool p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, address p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3) + ); } - function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3) + ); } - function log(uint256 p0, address p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3) + ); } - function log(uint256 p0, address p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3) + ); } - function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, address p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3) + ); } - function log(uint256 p0, address p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, string memory p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3) + ); } - function log(uint256 p0, address p1, string memory p2, address p3) internal view { + function log(uint256 p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3) + abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3) ); } - function log(uint256 p0, address p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, address p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, bool p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3) + ); } - function log(uint256 p0, address p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3)); } - function log(uint256 p0, address p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, bool p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3) + ); } - function log(uint256 p0, address p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3) + ); } - function log(uint256 p0, address p1, address p2, string memory p3) internal view { + function log(uint256 p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3) + abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3) ); } - function log(uint256 p0, address p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, address p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3) + ); } - function log(uint256 p0, address p1, address p2, address p3) internal view { + function log(uint256 p0, address p1, address p2, address p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3) + abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3) ); } - function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3) + ); } - function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3) + ); } - function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3) + ); } - function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3) + ); } - function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3) + ); } - function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3)); } - function log(string memory p0, uint256 p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3) + ); } - function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3) + ); } - function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3)); } - function log(string memory p0, uint256 p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3)); } - function log(string memory p0, uint256 p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3) + ); } - function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3) + ); } - function log(string memory p0, uint256 p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3) + ); } - function log(string memory p0, uint256 p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3) + ); } - function log(string memory p0, uint256 p1, address p2, address p3) internal view { + function log(string memory p0, uint256 p1, address p2, address p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3) + abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3) ); } - function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3) + ); } - function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3) + ); } - function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3) + ); } function log( @@ -863,771 +1012,871 @@ library console { string memory p1, string memory p2, string memory p3 - ) internal view { + ) internal pure { _sendLogPayload( abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3) ); } - function log(string memory p0, string memory p1, string memory p2, bool p3) internal view { + function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, string memory p2, address p3) internal view { + function log(string memory p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3) ); } - function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, bool p2, string memory p3) internal view { + function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, bool p2, bool p3) internal view { + function log(string memory p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, bool p2, address p3) internal view { + function log(string memory p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3) + ); } - function log(string memory p0, string memory p1, address p2, string memory p3) internal view { + function log(string memory p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3) ); } - function log(string memory p0, string memory p1, address p2, bool p3) internal view { + function log(string memory p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, address p2, address p3) internal view { + function log(string memory p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3) ); } - function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3) + ); } - function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, string memory p2, string memory p3) internal view { + function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, string memory p2, bool p3) internal view { + function log(string memory p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, string memory p2, address p3) internal view { + function log(string memory p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, bool p2, string memory p3) internal view { + function log(string memory p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, bool p2, bool p3) internal view { + function log(string memory p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, bool p2, address p3) internal view { + function log(string memory p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3) + ); } - function log(string memory p0, bool p1, address p2, string memory p3) internal view { + function log(string memory p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, address p2, bool p3) internal view { + function log(string memory p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, address p2, address p3) internal view { + function log(string memory p0, bool p1, address p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3) ); } - function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3)); + function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(string memory p0, address p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3)); + function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3) + ); } - function log(string memory p0, address p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3)); + function log(string memory p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3) + ); } - function log(string memory p0, address p1, uint256 p2, address p3) internal view { + function log(string memory p0, address p1, uint256 p2, address p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3) + abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3) ); } - function log(string memory p0, address p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3)); + function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3) + ); } - function log(string memory p0, address p1, string memory p2, string memory p3) internal view { + function log(string memory p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3) ); } - function log(string memory p0, address p1, string memory p2, bool p3) internal view { + function log(string memory p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, string memory p2, address p3) internal view { + function log(string memory p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3) ); } - function log(string memory p0, address p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3)); + function log(string memory p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3) + ); } - function log(string memory p0, address p1, bool p2, string memory p3) internal view { + function log(string memory p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, bool p2, bool p3) internal view { + function log(string memory p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, bool p2, address p3) internal view { + function log(string memory p0, address p1, bool p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3) ); } - function log(string memory p0, address p1, address p2, uint256 p3) internal view { + function log(string memory p0, address p1, address p2, uint256 p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3) + abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3) ); } - function log(string memory p0, address p1, address p2, string memory p3) internal view { + function log(string memory p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3) ); } - function log(string memory p0, address p1, address p2, bool p3) internal view { + function log(string memory p0, address p1, address p2, bool p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3) ); } - function log(string memory p0, address p1, address p2, address p3) internal view { + function log(string memory p0, address p1, address p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3) ); } - function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3) + ); } - function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3)); } - function log(bool p0, uint256 p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3) + ); } - function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3) + ); } - function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3)); } - function log(bool p0, uint256 p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3)); } - function log(bool p0, uint256 p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3) + ); } - function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3)); } - function log(bool p0, uint256 p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3)); } - function log(bool p0, uint256 p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3)); } - function log(bool p0, uint256 p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3)); } - function log(bool p0, uint256 p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3) + ); } - function log(bool p0, uint256 p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3) + ); } - function log(bool p0, uint256 p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3)); } - function log(bool p0, uint256 p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3) + ); } - function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3) + ); } - function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, string memory p2, string memory p3) internal view { + function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, string memory p2, bool p3) internal view { + function log(bool p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, string memory p2, address p3) internal view { + function log(bool p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, bool p2, string memory p3) internal view { + function log(bool p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, bool p2, bool p3) internal view { + function log(bool p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, bool p2, address p3) internal view { + function log(bool p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3) + ); } - function log(bool p0, string memory p1, address p2, string memory p3) internal view { + function log(bool p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, address p2, bool p3) internal view { + function log(bool p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, address p2, address p3) internal view { + function log(bool p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3) ); } - function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3)); + function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3)); + function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3)); + function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3)); + function log(bool p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3)); + function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, string memory p2, string memory p3) internal view { + function log(bool p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, string memory p2, bool p3) internal view { + function log(bool p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, string memory p2, address p3) internal view { + function log(bool p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3)); + function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, bool p2, string memory p3) internal view { + function log(bool p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, bool p2, bool p3) internal view { + function log(bool p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, bool p2, address p3) internal view { + function log(bool p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3)); + function log(bool p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, address p2, string memory p3) internal view { + function log(bool p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, address p2, bool p3) internal view { + function log(bool p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, address p2, address p3) internal view { + function log(bool p0, bool p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); } - function log(bool p0, address p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3)); + function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(bool p0, address p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3)); + function log(bool p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3) + ); } - function log(bool p0, address p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3)); + function log(bool p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3)); } - function log(bool p0, address p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3)); + function log(bool p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3) + ); } - function log(bool p0, address p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3)); + function log(bool p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3) + ); } - function log(bool p0, address p1, string memory p2, string memory p3) internal view { + function log(bool p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); } - function log(bool p0, address p1, string memory p2, bool p3) internal view { + function log(bool p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); } - function log(bool p0, address p1, string memory p2, address p3) internal view { + function log(bool p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3) ); } - function log(bool p0, address p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3)); + function log(bool p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3)); } - function log(bool p0, address p1, bool p2, string memory p3) internal view { + function log(bool p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); } - function log(bool p0, address p1, bool p2, bool p3) internal view { + function log(bool p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); } - function log(bool p0, address p1, bool p2, address p3) internal view { + function log(bool p0, address p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); } - function log(bool p0, address p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3)); + function log(bool p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3) + ); } - function log(bool p0, address p1, address p2, string memory p3) internal view { + function log(bool p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3) ); } - function log(bool p0, address p1, address p2, bool p3) internal view { + function log(bool p0, address p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); } - function log(bool p0, address p1, address p2, address p3) internal view { + function log(bool p0, address p1, address p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3) ); } - function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3) + ); } - function log(address p0, uint256 p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3) + ); } - function log(address p0, uint256 p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3) + ); } - function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3) + ); } - function log(address p0, uint256 p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3) + ); } - function log(address p0, uint256 p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3) + ); } - function log(address p0, uint256 p1, string memory p2, address p3) internal view { + function log(address p0, uint256 p1, string memory p2, address p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3) + abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3) ); } - function log(address p0, uint256 p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3) + ); } - function log(address p0, uint256 p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3) + ); } - function log(address p0, uint256 p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3)); } - function log(address p0, uint256 p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3) + ); } - function log(address p0, uint256 p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3) + ); } - function log(address p0, uint256 p1, address p2, string memory p3) internal view { + function log(address p0, uint256 p1, address p2, string memory p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3) + abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3) ); } - function log(address p0, uint256 p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3) + ); } - function log(address p0, uint256 p1, address p2, address p3) internal view { + function log(address p0, uint256 p1, address p2, address p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3) + abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3) ); } - function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3)); + function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(address p0, string memory p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3)); + function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3) + ); } - function log(address p0, string memory p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3)); + function log(address p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3) + ); } - function log(address p0, string memory p1, uint256 p2, address p3) internal view { + function log(address p0, string memory p1, uint256 p2, address p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3) + abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3) ); } - function log(address p0, string memory p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3)); + function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3) + ); } - function log(address p0, string memory p1, string memory p2, string memory p3) internal view { + function log(address p0, string memory p1, string memory p2, string memory p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3) ); } - function log(address p0, string memory p1, string memory p2, bool p3) internal view { + function log(address p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, string memory p2, address p3) internal view { + function log(address p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3) ); } - function log(address p0, string memory p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3)); + function log(address p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3) + ); } - function log(address p0, string memory p1, bool p2, string memory p3) internal view { + function log(address p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, bool p2, bool p3) internal view { + function log(address p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, bool p2, address p3) internal view { + function log(address p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3) ); } - function log(address p0, string memory p1, address p2, uint256 p3) internal view { + function log(address p0, string memory p1, address p2, uint256 p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3) + abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3) ); } - function log(address p0, string memory p1, address p2, string memory p3) internal view { + function log(address p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3) ); } - function log(address p0, string memory p1, address p2, bool p3) internal view { + function log(address p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3) ); } - function log(address p0, string memory p1, address p2, address p3) internal view { + function log(address p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3) ); } - function log(address p0, bool p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3)); + function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(address p0, bool p1, uint256 p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3)); + function log(address p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3) + ); } - function log(address p0, bool p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3)); + function log(address p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3)); } - function log(address p0, bool p1, uint256 p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3)); + function log(address p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3) + ); } - function log(address p0, bool p1, string memory p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3)); + function log(address p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3) + ); } - function log(address p0, bool p1, string memory p2, string memory p3) internal view { + function log(address p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); } - function log(address p0, bool p1, string memory p2, bool p3) internal view { + function log(address p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); } - function log(address p0, bool p1, string memory p2, address p3) internal view { + function log(address p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3) ); } - function log(address p0, bool p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3)); + function log(address p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3)); } - function log(address p0, bool p1, bool p2, string memory p3) internal view { + function log(address p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); } - function log(address p0, bool p1, bool p2, bool p3) internal view { + function log(address p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); } - function log(address p0, bool p1, bool p2, address p3) internal view { + function log(address p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); } - function log(address p0, bool p1, address p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3)); + function log(address p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3) + ); } - function log(address p0, bool p1, address p2, string memory p3) internal view { + function log(address p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3) ); } - function log(address p0, bool p1, address p2, bool p3) internal view { + function log(address p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); } - function log(address p0, bool p1, address p2, address p3) internal view { + function log(address p0, bool p1, address p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3) ); } - function log(address p0, address p1, uint256 p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3)); + function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3) + ); } - function log(address p0, address p1, uint256 p2, string memory p3) internal view { + function log(address p0, address p1, uint256 p2, string memory p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3) + abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3) ); } - function log(address p0, address p1, uint256 p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3)); + function log(address p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3) + ); } - function log(address p0, address p1, uint256 p2, address p3) internal view { + function log(address p0, address p1, uint256 p2, address p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3) + abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3) ); } - function log(address p0, address p1, string memory p2, uint256 p3) internal view { + function log(address p0, address p1, string memory p2, uint256 p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3) + abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3) ); } - function log(address p0, address p1, string memory p2, string memory p3) internal view { + function log(address p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3) ); } - function log(address p0, address p1, string memory p2, bool p3) internal view { + function log(address p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3) ); } - function log(address p0, address p1, string memory p2, address p3) internal view { + function log(address p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3) ); } - function log(address p0, address p1, bool p2, uint256 p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3)); + function log(address p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload( + abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3) + ); } - function log(address p0, address p1, bool p2, string memory p3) internal view { + function log(address p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3) ); } - function log(address p0, address p1, bool p2, bool p3) internal view { + function log(address p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); } - function log(address p0, address p1, bool p2, address p3) internal view { + function log(address p0, address p1, bool p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3) ); } - function log(address p0, address p1, address p2, uint256 p3) internal view { + function log(address p0, address p1, address p2, uint256 p3) internal pure { _sendLogPayload( - abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3) + abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3) ); } - function log(address p0, address p1, address p2, string memory p3) internal view { + function log(address p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3) ); } - function log(address p0, address p1, address p2, bool p3) internal view { + function log(address p0, address p1, address p2, bool p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3) ); } - function log(address p0, address p1, address p2, address p3) internal view { + function log(address p0, address p1, address p2, address p3) internal pure { _sendLogPayload( abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3) ); diff --git a/packages/contracts/evm-contracts/test-lib/ctest.sol b/packages/contracts/evm-contracts/test-lib/ctest.sol index 15339d958..ff47d2d9a 100644 --- a/packages/contracts/evm-contracts/test-lib/ctest.sol +++ b/packages/contracts/evm-contracts/test-lib/ctest.sol @@ -1,133 +1,678 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.5.0; -contract CTest { +import {StdInvariant} from "./StdInvariant.sol"; + +contract CTest is StdInvariant { event log(string); event logs(bytes); event log_address(address); event log_bytes32(bytes32); - event log_int(int256); - event log_uint(uint256); + event log_int(int); + event log_uint(uint); event log_bytes(bytes); event log_string(string); event log_named_address(string key, address val); event log_named_bytes32(string key, bytes32 val); - event log_named_decimal_int(string key, int256 val, uint256 decimals); - event log_named_decimal_uint(string key, uint256 val, uint256 decimals); - event log_named_int(string key, int256 val); - event log_named_uint(string key, uint256 val); + event log_named_decimal_int(string key, int val, uint decimals); + event log_named_decimal_uint(string key, uint val, uint decimals); + event log_named_int(string key, int val); + event log_named_uint(string key, uint val); event log_named_bytes(string key, bytes val); event log_named_string(string key, string val); - bool public failed; + bool public IS_TEST = true; + bool private _failed; + address constant HEVM_ADDRESS = address(bytes20(uint160(uint256(keccak256("hevm cheat code"))))); + address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; + uint256 private constant INT256_MIN_ABS = + 57896044618658097711785492504343953926634992332820282019728792003956564819968; + uint256 private constant UINT256_MAX = + 115792089237316195423570985008687907853269984665640564039457584007913129639935; + + modifier mayRevert() { + _; + } + modifier testopts(string memory) { + _; + } + + function failed() public returns (bool) { + if (_failed) { + return _failed; + } else { + bool globalFailed = false; + if (hasHEVMContext()) { + (, bytes memory retdata) = HEVM_ADDRESS.call( + abi.encodePacked( + bytes4(keccak256("load(address,bytes32)")), + abi.encode(HEVM_ADDRESS, bytes32("failed")) + ) + ); + globalFailed = abi.decode(retdata, (bool)); + } + return globalFailed; + } + } + + function fail() internal virtual { + if (hasHEVMContext()) { + (bool status, ) = HEVM_ADDRESS.call( + abi.encodePacked( + bytes4(keccak256("store(address,bytes32,bytes32)")), + abi.encode(HEVM_ADDRESS, bytes32("failed"), bytes32(uint256(0x01))) + ) + ); + status; // Silence compiler warnings + } + _failed = true; + } - function fail() internal { - failed = true; + function hasHEVMContext() internal view returns (bool) { + uint256 hevmCodeSize = 0; + assembly { + hevmCodeSize := extcodesize(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D) + } + return hevmCodeSize > 0; } - // modifier logs_gas() { - // uint startGas = gasleft(); - // _; - // uint endGas = gasleft(); - // emit log_named_uint("gas", startGas - endGas); - // } + modifier logs_gas() { + uint startGas = gasleft(); + _; + uint endGas = gasleft(); + emit log_named_uint("gas", startGas - endGas); + } - function assertTrue(bool condition) internal returns (bool) { + function assertTrue(bool condition) internal { if (!condition) { emit log("Error: Assertion Failed"); fail(); } - return condition; } - function assertTrue(bool condition, string memory err) internal returns (bool) { - if (bytes(err).length == 0) return assertTrue(condition); + function assertTrue(bool condition, string memory err) internal { if (!condition) { - emit log_named_string("Error:", err); - fail(); + emit log_named_string("Error", err); + assertTrue(condition); } - return condition; } function assertEq(address a, address b) internal { - assertEq(a, b, ""); + if (a != b) { + emit log("Error: a == b not satisfied [address]"); + emit log_named_address(" Left", a); + emit log_named_address(" Right", b); + fail(); + } } - function assertEq(address a, address b, string memory err) internal { - if (!assertTrue(a == b, err)) { - emit log("Reason: a == b not satisfied [address]"); - emit log_named_address(" Expected", b); - emit log_named_address(" Actual", a); + if (a != b) { + emit log_named_string("Error", err); + assertEq(a, b); } } function assertEq(bytes32 a, bytes32 b) internal { - assertEq(a, b, ""); + if (a != b) { + emit log("Error: a == b not satisfied [bytes32]"); + emit log_named_bytes32(" Left", a); + emit log_named_bytes32(" Right", b); + fail(); + } } - function assertEq(bytes32 a, bytes32 b, string memory err) internal { - if (!assertTrue(a == b, err)) { - emit log("Reason: a == b not satisfied [bytes32]"); - emit log_named_bytes32(" Expected", b); - emit log_named_bytes32(" Actual", a); + if (a != b) { + emit log_named_string("Error", err); + assertEq(a, b); } } + function assertEq32(bytes32 a, bytes32 b) internal { + assertEq(a, b); + } + function assertEq32(bytes32 a, bytes32 b, string memory err) internal { + assertEq(a, b, err); + } - function assertEq(int256 a, int256 b) internal { - assertEq(a, b, ""); + function assertEq(int a, int b) internal { + if (a != b) { + emit log("Error: a == b not satisfied [int]"); + emit log_named_int(" Left", a); + emit log_named_int(" Right", b); + fail(); + } + } + function assertEq(int a, int b, string memory err) internal { + if (a != b) { + emit log_named_string("Error", err); + assertEq(a, b); + } + } + function assertEq(uint a, uint b) internal { + if (a != b) { + emit log("Error: a == b not satisfied [uint]"); + emit log_named_uint(" Left", a); + emit log_named_uint(" Right", b); + fail(); + } + } + function assertEq(uint a, uint b, string memory err) internal { + if (a != b) { + emit log_named_string("Error", err); + assertEq(a, b); + } + } + function assertEqDecimal(int a, int b, uint decimals) internal { + if (a != b) { + emit log("Error: a == b not satisfied [decimal int]"); + emit log_named_decimal_int(" Left", a, decimals); + emit log_named_decimal_int(" Right", b, decimals); + fail(); + } + } + function assertEqDecimal(int a, int b, uint decimals, string memory err) internal { + if (a != b) { + emit log_named_string("Error", err); + assertEqDecimal(a, b, decimals); + } + } + function assertEqDecimal(uint a, uint b, uint decimals) internal { + if (a != b) { + emit log("Error: a == b not satisfied [decimal uint]"); + emit log_named_decimal_uint(" Left", a, decimals); + emit log_named_decimal_uint(" Right", b, decimals); + fail(); + } + } + function assertEqDecimal(uint a, uint b, uint decimals, string memory err) internal { + if (a != b) { + emit log_named_string("Error", err); + assertEqDecimal(a, b, decimals); + } } - function assertEq(int256 a, int256 b, string memory err) internal { - if (!assertTrue(a == b, err)) { - emit log("Reason: a == b not satisfied [int]"); - emit log_named_int(" Expected", b); - emit log_named_int(" Actual", a); + function assertNotEq(address a, address b) internal { + if (a == b) { + emit log("Error: a != b not satisfied [address]"); + emit log_named_address(" Left", a); + emit log_named_address(" Right", b); + fail(); + } + } + function assertNotEq(address a, address b, string memory err) internal { + if (a == b) { + emit log_named_string("Error", err); + assertNotEq(a, b); } } - function assertEq(uint256 a, uint256 b) internal { - assertEq(a, b, ""); + function assertNotEq(bytes32 a, bytes32 b) internal { + if (a == b) { + emit log("Error: a != b not satisfied [bytes32]"); + emit log_named_bytes32(" Left", a); + emit log_named_bytes32(" Right", b); + fail(); + } + } + function assertNotEq(bytes32 a, bytes32 b, string memory err) internal { + if (a == b) { + emit log_named_string("Error", err); + assertNotEq(a, b); + } + } + function assertNotEq32(bytes32 a, bytes32 b) internal { + assertNotEq(a, b); + } + function assertNotEq32(bytes32 a, bytes32 b, string memory err) internal { + assertNotEq(a, b, err); } - function assertEq(uint256 a, uint256 b, string memory err) internal { - if (!assertTrue(a == b, err)) { - emit log("Reason: a == b not satisfied [uint]"); - emit log_named_uint(" Expected", b); - emit log_named_uint(" Actual", a); + function assertNotEq(int a, int b) internal { + if (a == b) { + emit log("Error: a != b not satisfied [int]"); + emit log_named_int(" Left", a); + emit log_named_int(" Right", b); + fail(); + } + } + function assertNotEq(int a, int b, string memory err) internal { + if (a == b) { + emit log_named_string("Error", err); + assertNotEq(a, b); + } + } + function assertNotEq(uint a, uint b) internal { + if (a == b) { + emit log("Error: a != b not satisfied [uint]"); + emit log_named_uint(" Left", a); + emit log_named_uint(" Right", b); + fail(); + } + } + function assertNotEq(uint a, uint b, string memory err) internal { + if (a == b) { + emit log_named_string("Error", err); + assertNotEq(a, b); + } + } + function assertNotEqDecimal(int a, int b, uint decimals) internal { + if (a == b) { + emit log("Error: a != b not satisfied [decimal int]"); + emit log_named_decimal_int(" Left", a, decimals); + emit log_named_decimal_int(" Right", b, decimals); + fail(); + } + } + function assertNotEqDecimal(int a, int b, uint decimals, string memory err) internal { + if (a == b) { + emit log_named_string("Error", err); + assertNotEqDecimal(a, b, decimals); + } + } + function assertNotEqDecimal(uint a, uint b, uint decimals) internal { + if (a == b) { + emit log("Error: a != b not satisfied [decimal uint]"); + emit log_named_decimal_uint(" Left", a, decimals); + emit log_named_decimal_uint(" Right", b, decimals); + fail(); + } + } + function assertNotEqDecimal(uint a, uint b, uint decimals, string memory err) internal { + if (a == b) { + emit log_named_string("Error", err); + assertNotEqDecimal(a, b, decimals); } } - function assertEq(string memory a, string memory b) internal { - assertEq(a, b, ""); + function assertGt(uint a, uint b) internal { + if (a <= b) { + emit log("Error: a > b not satisfied [uint]"); + emit log_named_uint(" Value a", a); + emit log_named_uint(" Value b", b); + fail(); + } + } + function assertGt(uint a, uint b, string memory err) internal { + if (a <= b) { + emit log_named_string("Error", err); + assertGt(a, b); + } + } + function assertGt(int a, int b) internal { + if (a <= b) { + emit log("Error: a > b not satisfied [int]"); + emit log_named_int(" Value a", a); + emit log_named_int(" Value b", b); + fail(); + } + } + function assertGt(int a, int b, string memory err) internal { + if (a <= b) { + emit log_named_string("Error", err); + assertGt(a, b); + } + } + function assertGtDecimal(int a, int b, uint decimals) internal { + if (a <= b) { + emit log("Error: a > b not satisfied [decimal int]"); + emit log_named_decimal_int(" Value a", a, decimals); + emit log_named_decimal_int(" Value b", b, decimals); + fail(); + } + } + function assertGtDecimal(int a, int b, uint decimals, string memory err) internal { + if (a <= b) { + emit log_named_string("Error", err); + assertGtDecimal(a, b, decimals); + } + } + function assertGtDecimal(uint a, uint b, uint decimals) internal { + if (a <= b) { + emit log("Error: a > b not satisfied [decimal uint]"); + emit log_named_decimal_uint(" Value a", a, decimals); + emit log_named_decimal_uint(" Value b", b, decimals); + fail(); + } + } + function assertGtDecimal(uint a, uint b, uint decimals, string memory err) internal { + if (a <= b) { + emit log_named_string("Error", err); + assertGtDecimal(a, b, decimals); + } } + function assertGe(uint a, uint b) internal { + if (a < b) { + emit log("Error: a >= b not satisfied [uint]"); + emit log_named_uint(" Value a", a); + emit log_named_uint(" Value b", b); + fail(); + } + } + function assertGe(uint a, uint b, string memory err) internal { + if (a < b) { + emit log_named_string("Error", err); + assertGe(a, b); + } + } + function assertGe(int a, int b) internal { + if (a < b) { + emit log("Error: a >= b not satisfied [int]"); + emit log_named_int(" Value a", a); + emit log_named_int(" Value b", b); + fail(); + } + } + function assertGe(int a, int b, string memory err) internal { + if (a < b) { + emit log_named_string("Error", err); + assertGe(a, b); + } + } + function assertGeDecimal(int a, int b, uint decimals) internal { + if (a < b) { + emit log("Error: a >= b not satisfied [decimal int]"); + emit log_named_decimal_int(" Value a", a, decimals); + emit log_named_decimal_int(" Value b", b, decimals); + fail(); + } + } + function assertGeDecimal(int a, int b, uint decimals, string memory err) internal { + if (a < b) { + emit log_named_string("Error", err); + assertGeDecimal(a, b, decimals); + } + } + function assertGeDecimal(uint a, uint b, uint decimals) internal { + if (a < b) { + emit log("Error: a >= b not satisfied [decimal uint]"); + emit log_named_decimal_uint(" Value a", a, decimals); + emit log_named_decimal_uint(" Value b", b, decimals); + fail(); + } + } + function assertGeDecimal(uint a, uint b, uint decimals, string memory err) internal { + if (a < b) { + emit log_named_string("Error", err); + assertGeDecimal(a, b, decimals); + } + } + + function assertLt(uint a, uint b) internal { + if (a >= b) { + emit log("Error: a < b not satisfied [uint]"); + emit log_named_uint(" Value a", a); + emit log_named_uint(" Value b", b); + fail(); + } + } + function assertLt(uint a, uint b, string memory err) internal { + if (a >= b) { + emit log_named_string("Error", err); + assertLt(a, b); + } + } + function assertLt(int a, int b) internal { + if (a >= b) { + emit log("Error: a < b not satisfied [int]"); + emit log_named_int(" Value a", a); + emit log_named_int(" Value b", b); + fail(); + } + } + function assertLt(int a, int b, string memory err) internal { + if (a >= b) { + emit log_named_string("Error", err); + assertLt(a, b); + } + } + function assertLtDecimal(int a, int b, uint decimals) internal { + if (a >= b) { + emit log("Error: a < b not satisfied [decimal int]"); + emit log_named_decimal_int(" Value a", a, decimals); + emit log_named_decimal_int(" Value b", b, decimals); + fail(); + } + } + function assertLtDecimal(int a, int b, uint decimals, string memory err) internal { + if (a >= b) { + emit log_named_string("Error", err); + assertLtDecimal(a, b, decimals); + } + } + function assertLtDecimal(uint a, uint b, uint decimals) internal { + if (a >= b) { + emit log("Error: a < b not satisfied [decimal uint]"); + emit log_named_decimal_uint(" Value a", a, decimals); + emit log_named_decimal_uint(" Value b", b, decimals); + fail(); + } + } + function assertLtDecimal(uint a, uint b, uint decimals, string memory err) internal { + if (a >= b) { + emit log_named_string("Error", err); + assertLtDecimal(a, b, decimals); + } + } + + function assertLe(uint a, uint b) internal { + if (a > b) { + emit log("Error: a <= b not satisfied [uint]"); + emit log_named_uint(" Value a", a); + emit log_named_uint(" Value b", b); + fail(); + } + } + function assertLe(uint a, uint b, string memory err) internal { + if (a > b) { + emit log_named_string("Error", err); + assertLe(a, b); + } + } + function assertLe(int a, int b) internal { + if (a > b) { + emit log("Error: a <= b not satisfied [int]"); + emit log_named_int(" Value a", a); + emit log_named_int(" Value b", b); + fail(); + } + } + function assertLe(int a, int b, string memory err) internal { + if (a > b) { + emit log_named_string("Error", err); + assertLe(a, b); + } + } + function assertLeDecimal(int a, int b, uint decimals) internal { + if (a > b) { + emit log("Error: a <= b not satisfied [decimal int]"); + emit log_named_decimal_int(" Value a", a, decimals); + emit log_named_decimal_int(" Value b", b, decimals); + fail(); + } + } + function assertLeDecimal(int a, int b, uint decimals, string memory err) internal { + if (a > b) { + emit log_named_string("Error", err); + assertLeDecimal(a, b, decimals); + } + } + function assertLeDecimal(uint a, uint b, uint decimals) internal { + if (a > b) { + emit log("Error: a <= b not satisfied [decimal uint]"); + emit log_named_decimal_uint(" Value a", a, decimals); + emit log_named_decimal_uint(" Value b", b, decimals); + fail(); + } + } + function assertLeDecimal(uint a, uint b, uint decimals, string memory err) internal { + if (a > b) { + emit log_named_string("Error", err); + assertLeDecimal(a, b, decimals); + } + } + + function assertEq(string memory a, string memory b) internal { + if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) { + emit log("Error: a == b not satisfied [string]"); + emit log_named_string(" Left", a); + emit log_named_string(" Right", b); + fail(); + } + } function assertEq(string memory a, string memory b, string memory err) internal { - if (!assertTrue(keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b)), err)) { - emit log("Reason: a == b not satisfied [string]"); - emit log_named_string(" Expected", b); - emit log_named_string(" Actual", a); + if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) { + emit log_named_string("Error", err); + assertEq(a, b); } } - function checkEq0(bytes memory a, bytes memory b) internal pure returns (bool) { - if (a.length != b.length) return false; - for (uint256 i = 0; i < a.length; i++) if (a[i] != b[i]) return false; - return true; + function assertNotEq(string memory a, string memory b) internal { + if (keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b))) { + emit log("Error: a != b not satisfied [string]"); + emit log_named_string(" Left", a); + emit log_named_string(" Right", b); + fail(); + } + } + function assertNotEq(string memory a, string memory b, string memory err) internal { + if (keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b))) { + emit log_named_string("Error", err); + assertNotEq(a, b); + } } + function checkEq0(bytes memory a, bytes memory b) internal pure returns (bool ok) { + ok = true; + if (a.length == b.length) { + for (uint i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + ok = false; + } + } + } else { + ok = false; + } + } function assertEq0(bytes memory a, bytes memory b) internal { - assertEq0(a, b, ""); + if (!checkEq0(a, b)) { + emit log("Error: a == b not satisfied [bytes]"); + emit log_named_bytes(" Left", a); + emit log_named_bytes(" Right", b); + fail(); + } } - function assertEq0(bytes memory a, bytes memory b, string memory err) internal { - if (!assertTrue(checkEq0(a, b), err)) { - emit log("Reason: a == b not satisfied [bytes]"); - emit log_named_bytes(" Expected", b); - emit log_named_bytes(" Actual", a); + if (!checkEq0(a, b)) { + emit log_named_string("Error", err); + assertEq0(a, b); } } + + function assertNotEq0(bytes memory a, bytes memory b) internal { + if (checkEq0(a, b)) { + emit log("Error: a != b not satisfied [bytes]"); + emit log_named_bytes(" Left", a); + emit log_named_bytes(" Right", b); + fail(); + } + } + function assertNotEq0(bytes memory a, bytes memory b, string memory err) internal { + if (checkEq0(a, b)) { + emit log_named_string("Error", err); + assertNotEq0(a, b); + } + } + + function console2_log(string memory p0, uint256 p1) private view { + (bool status, ) = address(CONSOLE2_ADDRESS).staticcall( + abi.encodeWithSignature("log(string,uint256)", p0, p1) + ); + status; + } + + function console2_log(string memory p0, string memory p1) private view { + (bool status, ) = address(CONSOLE2_ADDRESS).staticcall( + abi.encodeWithSignature("log(string,string)", p0, p1) + ); + status; + } + + function _bound( + uint256 x, + uint256 min, + uint256 max + ) internal pure virtual returns (uint256 result) { + require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min."); + // If x is between min and max, return x directly. This is to ensure that dictionary values + // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188 + if (x >= min && x <= max) return x; + + uint256 size = max - min + 1; + + // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side. + // This helps ensure coverage of the min/max values. + if (x <= 3 && size > x) return min + x; + if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x); + + // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive. + if (x > max) { + uint256 diff = x - max; + uint256 rem = diff % size; + if (rem == 0) return max; + result = min + rem - 1; + } else if (x < min) { + uint256 diff = min - x; + uint256 rem = diff % size; + if (rem == 0) return min; + result = max - rem + 1; + } + } + + function bound( + uint256 x, + uint256 min, + uint256 max + ) internal view virtual returns (uint256 result) { + result = _bound(x, min, max); + console2_log("Bound Result", result); + } + + function _bound( + int256 x, + int256 min, + int256 max + ) internal pure virtual returns (int256 result) { + require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min."); + + // Shifting all int256 values to uint256 to use _bound function. The range of two types are: + // int256 : -(2**255) ~ (2**255 - 1) + // uint256: 0 ~ (2**256 - 1) + // So, add 2**255, INT256_MIN_ABS to the integer values. + // + // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow. + // So, use `~uint256(x) + 1` instead. + uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS); + uint256 _min = min < 0 + ? (INT256_MIN_ABS - ~uint256(min) - 1) + : (uint256(min) + INT256_MIN_ABS); + uint256 _max = max < 0 + ? (INT256_MIN_ABS - ~uint256(max) - 1) + : (uint256(max) + INT256_MIN_ABS); + + uint256 y = _bound(_x, _min, _max); + + // To move it back to int256 value, subtract INT256_MIN_ABS at here. + result = y < INT256_MIN_ABS + ? int256(~(INT256_MIN_ABS - y) + 1) + : int256(y - INT256_MIN_ABS); + } + + function bound(int256 x, int256 min, int256 max) internal view virtual returns (int256 result) { + result = _bound(x, min, max); + // console2_log("Bound result", vm.toString(result)); + } } diff --git a/packages/contracts/evm-contracts/test/OrderbookDex.t.sol b/packages/contracts/evm-contracts/test/OrderbookDex.t.sol new file mode 100644 index 000000000..3d78006e4 --- /dev/null +++ b/packages/contracts/evm-contracts/test/OrderbookDex.t.sol @@ -0,0 +1,537 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import {CheatCodes} from "../test-lib/cheatcodes.sol"; +import {CTest} from "../test-lib/ctest.sol"; +import "../test-lib/console.sol"; + +import {Address} from "@openzeppelin/contracts/utils/Address.sol"; +import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; +import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + +import {IInverseAppProjected1155} from "../contracts/token/IInverseAppProjected1155.sol"; +import {InverseAppProjected1155} from "../contracts/token/InverseAppProjected1155.sol"; +import {IOrderbookDex} from "../contracts/orderbook/IOrderbookDex.sol"; +import {OrderbookDex} from "../contracts/orderbook/OrderbookDex.sol"; + +contract OrderbookDexTest is CTest, ERC1155Holder { + using Address for address payable; + + CheatCodes vm = CheatCodes(HEVM_ADDRESS); + OrderbookDex public dex; + IInverseAppProjected1155 asset; + address alice = vm.addr(uint256(keccak256(abi.encodePacked("alice")))); + address boris = vm.addr(uint256(keccak256(abi.encodePacked("boris")))); + + function setUp() public { + asset = new InverseAppProjected1155("Gold", "GOLD", address(this)); + dex = new OrderbookDex(address(asset)); + asset.setApprovalForAll(address(dex), true); + vm.deal(alice, 1_000 ether); + vm.deal(boris, 1_000 ether); + } + + function testFuzz_createSellOrder_satisfiesRequirements( + uint256 assetAmount, + uint256 pricePerAsset + ) public { + vm.assume(assetAmount > 0 && pricePerAsset > 0); + + uint256 orderId = dex.currentOrderId(); + uint256 assetId = asset.mint(assetAmount, ""); + + vm.expectEmit(true, true, true, true); + emit IOrderbookDex.OrderCreated( + address(this), + orderId, + assetId, + assetAmount, + pricePerAsset + ); + dex.createSellOrder(assetId, assetAmount, pricePerAsset); + + IOrderbookDex.Order memory order = dex.getOrder(orderId); + assertEq(order.assetId, assetId); + assertEq(order.assetAmount, assetAmount); + assertEq(order.pricePerAsset, pricePerAsset); + assertEq(asset.balanceOf(address(dex), assetId), assetAmount); + } + + function testFuzz_createBatchSellOrder_satisfiesRequirements(uint256 orderCount) public { + orderCount = bound(orderCount, 0, 100); + uint256[] memory assetIds = new uint256[](orderCount); + uint256[] memory assetAmounts = new uint256[](orderCount); + uint256[] memory pricesPerAssets = new uint256[](orderCount); + + for (uint256 i = 0; i < orderCount; ++i) { + assetAmounts[i] = i == 0 ? 1 : i; + pricesPerAssets[i] = i == 0 ? 1 : i; + assetIds[i] = asset.mint(assetAmounts[i], ""); + } + + uint256 orderId = dex.currentOrderId(); + for (uint256 i = 0; i < orderCount; ++i) { + vm.expectEmit(true, true, true, true); + emit IOrderbookDex.OrderCreated( + address(this), + orderId + i, + assetIds[i], + assetAmounts[i], + pricesPerAssets[i] + ); + } + + uint256[] memory orderIds = dex.createBatchSellOrder( + assetIds, + assetAmounts, + pricesPerAssets + ); + + for (uint256 i = 0; i < orderCount; ++i) { + IOrderbookDex.Order memory order = dex.getOrder(orderIds[i]); + assertEq(order.assetId, assetIds[i]); + assertEq(order.assetAmount, assetAmounts[i]); + assertEq(order.pricePerAsset, pricesPerAssets[i]); + assertEq(asset.balanceOf(address(dex), assetIds[i]), assetAmounts[i]); + } + } + + function testFuzz_createBatchSellOrder_reverts_ifInvalidArrayLength( + uint256 length1, + uint256 length2, + uint256 length3 + ) public { + length1 = bound(length1, 0, 1000); + length2 = bound(length2, 0, 1000); + length3 = bound(length3, 0, 1000); + vm.assume(length1 != length2 || length2 != length3); + uint256[] memory assetIds = new uint256[](length1); + uint256[] memory assetAmounts = new uint256[](length2); + uint256[] memory pricesPerAssets = new uint256[](length3); + + vm.expectRevert(OrderbookDex.InvalidArrayLength.selector); + dex.createBatchSellOrder(assetIds, assetAmounts, pricesPerAssets); + } + + function testFuzz_createSellOrder_reverts_ifAssetAmountIsZero(uint256 pricePerAsset) public { + uint256 assetId = asset.mint(0, ""); + + vm.expectRevert(abi.encodeWithSelector(OrderbookDex.InvalidInput.selector, 0)); + dex.createSellOrder(assetId, 0, pricePerAsset); + } + + function testFuzz_fillOrdersExactEth_transfersCorrectly(uint256 price) public { + uint256 ordersCount = 5; + vm.assume(price / ordersCount > 0); + vm.assume(price < type(uint256).max / ordersCount); + uint256[] memory orderIds = new uint256[](ordersCount); + address payable[] memory sellers = new address payable[](ordersCount); + uint256 totalAssetAmount; + address buyer = address(this); + for (uint256 i = 0; i < ordersCount; i++) { + address payable seller = payable(vm.addr(uint256(keccak256(abi.encodePacked(i))))); + uint256 assetAmount = price / (ordersCount - i); + uint256 pricePerAsset = price / assetAmount; + orderIds[i] = dex.currentOrderId(); + sellers[i] = seller; + vm.startPrank(seller); + uint256 assetId = asset.mint(assetAmount, ""); + asset.setApprovalForAll(address(dex), true); + dex.createSellOrder(assetId, assetAmount, pricePerAsset); + totalAssetAmount += assetAmount; + } + + { + vm.deal(buyer, type(uint256).max); + uint256 buyerBalanceBefore = buyer.balance; + uint256[] memory sellersBalancesBefore = new uint256[](ordersCount); + uint256[] memory expectedPayouts = new uint256[](ordersCount); + uint256[] memory ordersAssetAmounts = new uint256[](ordersCount); + uint256 totalExpectedPayout; + for (uint256 i = 0; i < ordersCount; i++) { + IOrderbookDex.Order memory order = dex.getOrder(orderIds[i]); + expectedPayouts[i] = order.pricePerAsset * order.assetAmount; + ordersAssetAmounts[i] = order.assetAmount; + totalExpectedPayout += expectedPayouts[i]; + sellersBalancesBefore[i] = sellers[i].balance; + vm.expectEmit(true, true, true, true); + emit IOrderbookDex.OrderFilled( + sellers[i], + orderIds[i], + buyer, + order.assetAmount, + order.pricePerAsset + ); + } + vm.startPrank(buyer); + dex.fillOrdersExactEth{value: totalExpectedPayout + 1000}(totalAssetAmount, orderIds); + + assertEq(buyer.balance, buyerBalanceBefore - totalExpectedPayout); + for (uint256 i = 0; i < ordersCount; i++) { + IOrderbookDex.Order memory order = dex.getOrder(orderIds[i]); + assertEq(sellers[i].balance, sellersBalancesBefore[i] + expectedPayouts[i]); + assertEq(order.assetAmount, 0); + assertEq(asset.balanceOf(address(dex), order.assetId), 0); + assertEq(asset.balanceOf(buyer, order.assetId), ordersAssetAmounts[i]); + } + } + } + + function testFuzz_fillOrdersExactAsset_transfersCorrectly(uint256 price) public { + uint256 ordersCount = 5; + vm.assume(price / ordersCount > 0); + vm.assume(price < type(uint256).max / ordersCount); + uint256[] memory orderIds = new uint256[](ordersCount); + address payable[] memory sellers = new address payable[](ordersCount); + uint256 totalAssetAmount; + address buyer = address(this); + for (uint256 i = 0; i < ordersCount; i++) { + address payable seller = payable(vm.addr(uint256(keccak256(abi.encodePacked(i))))); + uint256 assetAmount = price / (ordersCount - i); + uint256 pricePerAsset = price / assetAmount; + orderIds[i] = dex.currentOrderId(); + sellers[i] = seller; + vm.startPrank(seller); + uint256 assetId = asset.mint(assetAmount, ""); + asset.setApprovalForAll(address(dex), true); + dex.createSellOrder(assetId, assetAmount, pricePerAsset); + totalAssetAmount += assetAmount; + } + + { + vm.deal(buyer, type(uint256).max); + uint256 buyerBalanceBefore = buyer.balance; + uint256[] memory sellersBalancesBefore = new uint256[](ordersCount); + uint256[] memory expectedPayouts = new uint256[](ordersCount); + uint256[] memory ordersAssetAmounts = new uint256[](ordersCount); + uint256 totalExpectedPayout; + for (uint256 i = 0; i < ordersCount; i++) { + IOrderbookDex.Order memory order = dex.getOrder(orderIds[i]); + expectedPayouts[i] = order.pricePerAsset * order.assetAmount; + ordersAssetAmounts[i] = order.assetAmount; + totalExpectedPayout += expectedPayouts[i]; + sellersBalancesBefore[i] = sellers[i].balance; + vm.expectEmit(true, true, true, true); + emit IOrderbookDex.OrderFilled( + sellers[i], + orderIds[i], + buyer, + order.assetAmount, + order.pricePerAsset + ); + } + vm.startPrank(buyer); + dex.fillOrdersExactAsset{value: totalExpectedPayout + 1000}(totalAssetAmount, orderIds); + + assertEq(buyer.balance, buyerBalanceBefore - totalExpectedPayout); + for (uint256 i = 0; i < ordersCount; i++) { + IOrderbookDex.Order memory order = dex.getOrder(orderIds[i]); + assertEq(sellers[i].balance, sellersBalancesBefore[i] + expectedPayouts[i]); + assertEq(order.assetAmount, 0); + assertEq(asset.balanceOf(address(dex), order.assetId), 0); + assertEq(asset.balanceOf(buyer, order.assetId), ordersAssetAmounts[i]); + } + } + } + + function testFuzz_fillOrdersExactEth_transfersCorrectlyWithPartialFill( + uint256 assetAmount, + uint256 pricePerAsset, + uint256 assetAmountToBuy + ) public { + vm.assume(assetAmount > 0 && pricePerAsset > 0); + vm.assume(assetAmount < type(uint256).max / pricePerAsset); + vm.assume(pricePerAsset < type(uint256).max / assetAmount); + vm.assume(assetAmountToBuy < assetAmount); + + address buyer = alice; + address payable seller = payable(address(this)); + vm.deal(buyer, assetAmount * pricePerAsset); + uint256 orderId = dex.currentOrderId(); + vm.startPrank(seller); + uint256 assetId = asset.mint(assetAmount, ""); + asset.setApprovalForAll(address(dex), true); + dex.createSellOrder(assetId, assetAmount, pricePerAsset); + + uint256 buyerBalanceBefore = buyer.balance; + uint256 sellerBalanceBefore = seller.balance; + uint256[] memory orderIds = new uint256[](1); + orderIds[0] = orderId; + vm.startPrank(buyer); + dex.fillOrdersExactEth{value: assetAmountToBuy * pricePerAsset}(assetAmountToBuy, orderIds); + + IOrderbookDex.Order memory order = dex.getOrder(orderId); + assertEq(buyer.balance, buyerBalanceBefore - (assetAmountToBuy * pricePerAsset)); + assertEq(seller.balance, sellerBalanceBefore + (assetAmountToBuy * pricePerAsset)); + assertEq(order.assetAmount, assetAmount - assetAmountToBuy); + assertEq(asset.balanceOf(address(dex), assetId), assetAmount - assetAmountToBuy); + assertEq(asset.balanceOf(buyer, assetId), assetAmountToBuy); + } + + function testFuzz_fillOrdersExactAsset_transfersCorrectlyWithPartialFill( + uint256 assetAmount, + uint256 pricePerAsset, + uint256 assetAmountToBuy + ) public { + vm.assume(assetAmount > 0 && pricePerAsset > 0); + vm.assume(assetAmount < type(uint256).max / pricePerAsset); + vm.assume(pricePerAsset < type(uint256).max / assetAmount); + vm.assume(assetAmountToBuy < assetAmount); + + address buyer = alice; + address payable seller = payable(address(this)); + vm.deal(buyer, assetAmount * pricePerAsset); + uint256 orderId = dex.currentOrderId(); + vm.startPrank(seller); + uint256 assetId = asset.mint(assetAmount, ""); + asset.setApprovalForAll(address(dex), true); + dex.createSellOrder(assetId, assetAmount, pricePerAsset); + + uint256 buyerBalanceBefore = buyer.balance; + uint256 sellerBalanceBefore = seller.balance; + uint256[] memory orderIds = new uint256[](1); + orderIds[0] = orderId; + vm.startPrank(buyer); + dex.fillOrdersExactAsset{value: buyerBalanceBefore}(assetAmountToBuy, orderIds); + + IOrderbookDex.Order memory order = dex.getOrder(orderId); + assertEq(buyer.balance, buyerBalanceBefore - (assetAmountToBuy * pricePerAsset)); + assertEq(seller.balance, sellerBalanceBefore + (assetAmountToBuy * pricePerAsset)); + assertEq(order.assetAmount, assetAmount - assetAmountToBuy); + assertEq(asset.balanceOf(address(dex), assetId), assetAmount - assetAmountToBuy); + assertEq(asset.balanceOf(buyer, assetId), assetAmountToBuy); + } + + function testFuzz_fillOrdersExactEth_refundsExcessValue( + uint256 assetAmount, + uint256 pricePerAsset + ) public { + uint256 multiplier = 3; + vm.assume(assetAmount > 0 && pricePerAsset > 0); + vm.assume(assetAmount < type(uint256).max / pricePerAsset / multiplier); + vm.assume(pricePerAsset < type(uint256).max / assetAmount / multiplier); + + vm.deal(alice, assetAmount * pricePerAsset * multiplier); + uint256 orderId = dex.currentOrderId(); + uint256 assetId = asset.mint(assetAmount, ""); + dex.createSellOrder(assetId, assetAmount, pricePerAsset); + + uint256 aliceBalanceBefore = alice.balance; + uint256[] memory orderIds = new uint256[](1); + orderIds[0] = orderId; + vm.startPrank(alice); + dex.fillOrdersExactEth{value: alice.balance}(assetAmount, orderIds); + assertEq(alice.balance, aliceBalanceBefore - (assetAmount * pricePerAsset)); + } + + function testFuzz_fillOrdersExactAsset_refundsExcessValue( + uint256 assetAmount, + uint256 pricePerAsset + ) public { + uint256 multiplier = 3; + vm.assume(assetAmount > 0 && pricePerAsset > 0); + vm.assume(assetAmount < type(uint256).max / pricePerAsset / multiplier); + vm.assume(pricePerAsset < type(uint256).max / assetAmount / multiplier); + + vm.deal(alice, assetAmount * pricePerAsset * multiplier); + uint256 orderId = dex.currentOrderId(); + uint256 assetId = asset.mint(assetAmount, ""); + dex.createSellOrder(assetId, assetAmount, pricePerAsset); + + uint256 aliceBalanceBefore = alice.balance; + uint256[] memory orderIds = new uint256[](1); + orderIds[0] = orderId; + vm.startPrank(alice); + dex.fillOrdersExactAsset{value: alice.balance}(assetAmount, orderIds); + assertEq(alice.balance, aliceBalanceBefore - (assetAmount * pricePerAsset)); + } + + function test_fillOrdersExactEth_wontFillOrderIfOrderWasCancelled() public { + uint256 assetAmount = 100; + uint256 pricePerAsset = 200; + uint256 orderId = dex.currentOrderId(); + uint256 assetId = asset.mint(assetAmount, ""); + dex.createSellOrder(assetId, assetAmount, pricePerAsset); + dex.cancelSellOrder(orderId); + + uint256 aliceBalanceBefore = alice.balance; + uint256[] memory orderIds = new uint256[](1); + orderIds[0] = orderId; + vm.startPrank(alice); + + dex.fillOrdersExactEth{value: assetAmount * pricePerAsset}(0, orderIds); + assertEq(alice.balance, aliceBalanceBefore); + } + + function test_fillOrdersExactAsset_wontFillOrderIfOrderWasCancelled() public { + uint256 assetAmount = 100; + uint256 pricePerAsset = 200; + uint256 orderId = dex.currentOrderId(); + uint256 assetId = asset.mint(assetAmount, ""); + dex.createSellOrder(assetId, assetAmount, pricePerAsset); + dex.cancelSellOrder(orderId); + + uint256 aliceBalanceBefore = alice.balance; + uint256[] memory orderIds = new uint256[](1); + orderIds[0] = orderId; + vm.startPrank(alice); + + dex.fillOrdersExactAsset{value: assetAmount * pricePerAsset}(0, orderIds); + assertEq(alice.balance, aliceBalanceBefore); + } + + function test_fillOrdersExactEth_reverts_ifInsufficientEndAmount() public { + uint256 assetAmount = 10; + uint256 pricePerAsset = 100; + uint256 orderId = dex.currentOrderId(); + uint256 assetId = asset.mint(assetAmount, ""); + dex.createSellOrder(assetId, assetAmount, pricePerAsset); + + address payable[] memory sellers = new address payable[](1); + sellers[0] = payable(address(this)); + uint256[] memory orderIds = new uint256[](1); + orderIds[0] = orderId; + vm.startPrank(alice); + vm.expectRevert( + abi.encodeWithSelector( + OrderbookDex.InsufficientEndAmount.selector, + assetAmount + 1, + assetAmount + ) + ); + dex.fillOrdersExactEth{value: assetAmount * pricePerAsset}(assetAmount + 1, orderIds); + } + + function test_fillOrdersExactAsset_reverts_ifInsufficientEndAmount() public { + uint256 assetAmount = 10; + uint256 pricePerAsset = 100; + uint256 orderId = dex.currentOrderId(); + uint256 assetId = asset.mint(assetAmount, ""); + dex.createSellOrder(assetId, assetAmount, pricePerAsset); + + address payable[] memory sellers = new address payable[](1); + sellers[0] = payable(address(this)); + uint256[] memory orderIds = new uint256[](1); + orderIds[0] = orderId; + vm.startPrank(alice); + vm.expectRevert( + abi.encodeWithSelector( + OrderbookDex.InsufficientEndAmount.selector, + assetAmount + 1, + assetAmount + ) + ); + dex.fillOrdersExactAsset{value: assetAmount * pricePerAsset}(assetAmount + 1, orderIds); + } + + function test_supportsInterface_returnsTrueForImplementedInterfaces() public { + assertTrue(dex.supportsInterface(type(IERC165).interfaceId)); + assertTrue(dex.supportsInterface(type(IERC165).interfaceId)); + assertTrue(dex.supportsInterface(type(IOrderbookDex).interfaceId)); + } + + function testFuzz_cancelSellOrder_satisfiesRequirements(uint256 assetAmount) public { + vm.assume(assetAmount > 0); + uint256 assetId = asset.mint(assetAmount, ""); + uint256 orderId = dex.currentOrderId(); + dex.createSellOrder(assetId, assetAmount, 200); + + vm.expectEmit(true, true, true, true); + emit IOrderbookDex.OrderCancelled(address(this), orderId); + dex.cancelSellOrder(orderId); + IOrderbookDex.Order memory order = dex.getOrder(orderId); + assertEq(order.assetAmount, 0); + assertEq(asset.balanceOf(address(dex), assetId), 0); + assertEq(asset.balanceOf(address(this), assetId), assetAmount); + } + + function test_cancelSellOrder_reverts_ifUnauthorized() public { + uint256 orderId = dex.currentOrderId(); + uint256 assetId = asset.mint(100, ""); + dex.createSellOrder(assetId, 100, 200); + + vm.startPrank(alice); + vm.expectRevert(abi.encodeWithSelector(OrderbookDex.Unauthorized.selector, alice)); + dex.cancelSellOrder(orderId); + } + + function testFuzz_cancelBatchSellOrder_satisfiesRequirements(uint256 orderCount) public { + orderCount = bound(orderCount, 0, 100); + uint256[] memory assetIds = new uint256[](orderCount); + uint256[] memory assetAmounts = new uint256[](orderCount); + uint256[] memory pricesPerAssets = new uint256[](orderCount); + + for (uint256 i = 0; i < orderCount; ++i) { + assetAmounts[i] = i == 0 ? 1 : i; + pricesPerAssets[i] = i == 0 ? 1 : i; + assetIds[i] = asset.mint(assetAmounts[i], ""); + } + + uint256 orderId = dex.currentOrderId(); + + uint256[] memory orderIds = dex.createBatchSellOrder( + assetIds, + assetAmounts, + pricesPerAssets + ); + + for (uint256 i = 0; i < orderCount; ++i) { + vm.expectEmit(true, true, true, true); + emit IOrderbookDex.OrderCancelled(address(this), orderId + i); + } + + dex.cancelBatchSellOrder(orderIds); + + for (uint256 i = 0; i < orderCount; ++i) { + IOrderbookDex.Order memory order = dex.getOrder(orderIds[i]); + assertEq(order.assetAmount, 0); + assertEq(asset.balanceOf(address(dex), assetIds[i]), 0); + assertEq(asset.balanceOf(address(this), assetIds[i]), assetAmounts[i]); + } + } + + function test_cancelBatchSellOrder_reverts_ifUnauthorized() public { + uint256 orderId = dex.currentOrderId(); + uint256 assetId = asset.mint(100, ""); + dex.createSellOrder(assetId, 100, 200); + + uint256[] memory orderIds = new uint256[](1); + orderIds[0] = orderId; + + vm.startPrank(alice); + vm.expectRevert(abi.encodeWithSelector(OrderbookDex.Unauthorized.selector, alice)); + dex.cancelBatchSellOrder(orderIds); + } + + // Not really a test, was used to measure gas usage + function test_fillOrders_getGasUsage() public { + uint256 orderCount = 500; + uint256[] memory assetIds = new uint256[](orderCount); + uint256[] memory assetAmounts = new uint256[](orderCount); + uint256[] memory pricesPerAssets = new uint256[](orderCount); + + for (uint256 i = 0; i < orderCount; ++i) { + assetAmounts[i] = i == 0 ? 1 : i; + pricesPerAssets[i] = i == 0 ? 1 : i; + assetIds[i] = asset.mint(assetAmounts[i], ""); + } + uint256[] memory orderIds = dex.createBatchSellOrder( + assetIds, + assetAmounts, + pricesPerAssets + ); + + assertEq(orderIds.length, orderCount); + + uint256 minimumAsset = 1; + uint256 value = type(uint256).max; + vm.deal(address(this), value); + + uint256 startGas = gasleft(); + dex.fillOrdersExactEth{value: value}(minimumAsset, orderIds); + console.log("fill orders gas used", startGas - gasleft()); + } + + receive() external payable {} +} diff --git a/packages/contracts/evm-contracts/test/OrderbookDexInvariant.t.sol b/packages/contracts/evm-contracts/test/OrderbookDexInvariant.t.sol new file mode 100644 index 000000000..ddfed6dc9 --- /dev/null +++ b/packages/contracts/evm-contracts/test/OrderbookDexInvariant.t.sol @@ -0,0 +1,390 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import {CheatCodes} from "../test-lib/cheatcodes.sol"; +import {CTest} from "../test-lib/ctest.sol"; + +import {Address} from "@openzeppelin/contracts/utils/Address.sol"; +import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; +import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + +import {IInverseAppProjected1155} from "../contracts/token/IInverseAppProjected1155.sol"; +import {InverseAppProjected1155} from "../contracts/token/InverseAppProjected1155.sol"; +import {IOrderbookDex} from "../contracts/orderbook/IOrderbookDex.sol"; +import {OrderbookDex} from "../contracts/orderbook/OrderbookDex.sol"; + +contract AssetHandler is CTest { + CheatCodes vm = CheatCodes(HEVM_ADDRESS); + IOrderbookDex public dex; + IInverseAppProjected1155 asset; + + constructor(IInverseAppProjected1155 _asset, IOrderbookDex _dex) { + asset = _asset; + dex = _dex; + } + + function safeTransferFrom( + address from, + address to, + uint256 id, + uint256 value, + bytes calldata data + ) public { + vm.assume(asset.balanceOf(from, id) >= value); + address sender = msg.sender; + vm.prank(from); + asset.setApprovalForAll(sender, true); + vm.prank(sender); + asset.safeTransferFrom(from, to, id, value, data); + } + + function safeBatchTransferFrom( + address from, + address to, + uint256[] calldata ids, + uint256[] calldata values, + bytes calldata data + ) public { + vm.assume(ids.length == values.length); + for (uint256 i; i < ids.length; ++i) { + vm.assume(asset.balanceOf(from, ids[i]) >= values[i]); + } + address sender = msg.sender; + vm.prank(from); + asset.setApprovalForAll(sender, true); + vm.prank(sender); + asset.safeBatchTransferFrom(from, to, ids, values, data); + } +} + +contract OrderbookDexHandler is CTest, ERC1155Holder { + CheatCodes vm = CheatCodes(HEVM_ADDRESS); + IOrderbookDex public dex; + IInverseAppProjected1155 asset; + + // Reasonable limits resulting in acceptable testing time + uint256 constant MAX_ASSET_AMOUNT = 100 ether; + uint256 constant MAX_PRICE = 1 ether; + uint256 constant MAX_BATCH_CREATE_SELL_ORDER = 50; + uint256 constant MAX_BATCH_CANCEL_SELL_ORDER = 10; + uint256 constant MAX_ORDER_FILL_LENGTH = 5; + + // Helper variables + mapping(uint256 tokenId => uint256) buyerTokenBalanceBefore; + mapping(uint256 tokenId => uint256) expectedTokenBalanceGain; + mapping(uint256 orderId => bool) orderIdUsed; + uint256[] newOrderIds; + uint256 public previousOrderId; + + address internal currentActor; + + modifier useActor(uint256 actorIndexSeed) { + _useActor(actorIndexSeed); + _; + vm.stopPrank(); + } + + function _useActor(uint256 actorIndexSeed) internal { + uint256 actorIndex = bound(actorIndexSeed, 1, 100); + currentActor = address(uint160(uint256(keccak256(abi.encodePacked(actorIndex))))); + vm.startPrank(currentActor); + } + + constructor(IInverseAppProjected1155 _asset, IOrderbookDex _dex) { + asset = _asset; + dex = _dex; + } + + function createSellOrder( + uint256 assetId, + uint256 assetAmount, + uint256 price, + uint256 actorIndexSeed + ) public useActor(actorIndexSeed) returns (uint256) { + // Bound amount and price to reasonable limits, mint the asset and set approval for the dex + assetAmount = bound(assetAmount, 1, MAX_ASSET_AMOUNT); + price = bound(price, 1, MAX_PRICE); + assetId = asset.mint(assetAmount, ""); + asset.setApprovalForAll(address(dex), true); + + // Take note of the previous order id + previousOrderId = dex.currentOrderId(); + + // Execute the sell order creation + return dex.createSellOrder(assetId, assetAmount, price); + } + + function createBatchSellOrder( + uint256[] memory assetAmounts, + uint256[] memory pricesPerAssets, + uint256 actorIndexSeed + ) public useActor(actorIndexSeed) returns (uint256[] memory) { + // Use the smaller of the input arrays length and bound it to a reasonable limit + uint256 smallestLength = assetAmounts.length; + if (pricesPerAssets.length < smallestLength) { + smallestLength = pricesPerAssets.length; + } + smallestLength = bound(smallestLength, 0, MAX_BATCH_CREATE_SELL_ORDER); + + // Bound amounts and prices to reasonable limits, mint the assets and set approval for the dex + uint256[] memory newAssetIds = new uint256[](smallestLength); + uint256[] memory newAssetAmounts = new uint256[](smallestLength); + uint256[] memory newPricesPerAssets = new uint256[](smallestLength); + for (uint256 i; i < smallestLength; ++i) { + newAssetAmounts[i] = bound(assetAmounts[i], 1, MAX_ASSET_AMOUNT); + newPricesPerAssets[i] = bound(pricesPerAssets[i], 1, MAX_PRICE); + newAssetIds[i] = asset.mint(newAssetAmounts[i], ""); + } + asset.setApprovalForAll(address(dex), true); + + // Execute the batch sell order creation + return dex.createBatchSellOrder(newAssetIds, newAssetAmounts, newPricesPerAssets); + } + + function fillOrdersExactEth( + uint256 minimumAsset, + uint256[] memory orderIds, + uint256 actorIndexSeed + ) public payable useActor(actorIndexSeed) { + // Bound the input length to a reasonable limit + uint256 inputLength = orderIds.length; + inputLength = bound(inputLength, 0, MAX_ORDER_FILL_LENGTH); + + // Calculate the sum of the asset amounts and prices of the orders + uint256 sumAssetAmount; + uint256 sumPrice; + for (uint256 i; i < inputLength; ++i) { + IOrderbookDex.Order memory order = dex.getOrder(orderIds[i]); + + if (!orderIdUsed[orderIds[i]]) { + sumAssetAmount += order.assetAmount; + sumPrice += order.pricePerAsset * order.assetAmount; + orderIdUsed[orderIds[i]] = true; + newOrderIds.push(orderIds[i]); + } + } + inputLength = newOrderIds.length; + + // Cap the asset amount to the sum of the asset amounts of the orders + if (minimumAsset > sumAssetAmount) { + minimumAsset = sumAssetAmount; + } + + // Set current actor's balance to expected total price to avoid revert + uint256 value = sumPrice; + vm.deal(currentActor, value); + + // Take note of buyer's tokens balances and orders' asset amounts before filling orders + // for the assertions later + uint256[] memory orderAssetAmountBefore = new uint256[](inputLength); + for (uint256 i; i < inputLength; ++i) { + IOrderbookDex.Order memory order = dex.getOrder(newOrderIds[i]); + buyerTokenBalanceBefore[order.assetId] = asset.balanceOf(currentActor, order.assetId); + orderAssetAmountBefore[i] = order.assetAmount; + } + + // Execute the fills + dex.fillOrdersExactEth{value: value}(minimumAsset, newOrderIds); + + // Calculate the expected token balance gain for each token + for (uint256 i; i < inputLength; ++i) { + IOrderbookDex.Order memory order = dex.getOrder(newOrderIds[i]); + expectedTokenBalanceGain[order.assetId] += + orderAssetAmountBefore[i] - + order.assetAmount; + } + + // Assert that the buyer's token balances have increased by the expected amount (that was credited from the orders' asset amounts) + for (uint256 i; i < inputLength; ++i) { + IOrderbookDex.Order memory order = dex.getOrder(newOrderIds[i]); + assertEq( + asset.balanceOf(currentActor, order.assetId), + buyerTokenBalanceBefore[order.assetId] + expectedTokenBalanceGain[order.assetId] + ); + } + + // Clean-up + for (uint256 i; i < inputLength; ++i) { + IOrderbookDex.Order memory order = dex.getOrder(newOrderIds[i]); + delete expectedTokenBalanceGain[order.assetId]; + delete orderIdUsed[newOrderIds[i]]; + } + delete newOrderIds; + } + + function fillOrdersExactAsset( + uint256 assetAmount, + uint256[] memory orderIds, + uint256 actorIndexSeed + ) public payable useActor(actorIndexSeed) { + // Bound the input length to a reasonable limit + uint256 inputLength = orderIds.length; + inputLength = bound(inputLength, 0, MAX_ORDER_FILL_LENGTH); + + // Calculate the sum of the asset amounts and prices of the orders + uint256 sumAssetAmount; + uint256 sumPrice; + for (uint256 i; i < inputLength; ++i) { + IOrderbookDex.Order memory order = dex.getOrder(orderIds[i]); + + if (!orderIdUsed[orderIds[i]]) { + sumAssetAmount += order.assetAmount; + sumPrice += order.pricePerAsset * order.assetAmount; + orderIdUsed[orderIds[i]] = true; + newOrderIds.push(orderIds[i]); + } + } + inputLength = newOrderIds.length; + + // Cap the asset amount to the sum of the asset amounts of the orders + if (assetAmount > sumAssetAmount) { + assetAmount = sumAssetAmount; + } + + // Set current actor's balance to expected total price plus 100 to avoid revert and + // to provide surplus which should be refunded + uint256 value = sumPrice + 100; + vm.deal(currentActor, value); + + // Take note of buyer's tokens balances and orders' asset amounts before filling orders + // for the assertions later + uint256[] memory orderAssetAmountBefore = new uint256[](inputLength); + for (uint256 i; i < inputLength; ++i) { + IOrderbookDex.Order memory order = dex.getOrder(newOrderIds[i]); + buyerTokenBalanceBefore[order.assetId] = asset.balanceOf(currentActor, order.assetId); + orderAssetAmountBefore[i] = order.assetAmount; + } + + // Execute the fills + dex.fillOrdersExactAsset{value: value}(assetAmount, newOrderIds); + + // Calculate the expected token balance gain for each token + for (uint256 i; i < inputLength; ++i) { + IOrderbookDex.Order memory order = dex.getOrder(newOrderIds[i]); + expectedTokenBalanceGain[order.assetId] += + orderAssetAmountBefore[i] - + order.assetAmount; + } + + // Assert that the buyer's token balances have increased by the expected amount (that was credited from the orders' asset amounts) + for (uint256 i; i < inputLength; ++i) { + IOrderbookDex.Order memory order = dex.getOrder(newOrderIds[i]); + assertEq( + asset.balanceOf(currentActor, order.assetId), + buyerTokenBalanceBefore[order.assetId] + expectedTokenBalanceGain[order.assetId] + ); + } + + // Clean-up + for (uint256 i; i < inputLength; ++i) { + IOrderbookDex.Order memory order = dex.getOrder(newOrderIds[i]); + delete expectedTokenBalanceGain[order.assetId]; + delete orderIdUsed[newOrderIds[i]]; + } + delete newOrderIds; + } + + function cancelSellOrder( + uint256 orderId, + uint256 actorIndexSeed + ) public useActor(actorIndexSeed) { + // If the order does not exist, get the last order id + if (dex.getOrder(orderId).assetAmount == 0) { + orderId = dex.currentOrderId(); + // If there are no orders, return + if (orderId == 0) { + return; + } else { + orderId--; + } + } + + // Assert that you can't cancel an order if you're not the seller + address seller = dex.getOrder(orderId).seller; + if (currentActor != seller) { + vm.expectRevert( + abi.encodeWithSelector(OrderbookDex.Unauthorized.selector, currentActor) + ); + dex.cancelSellOrder(orderId); + } + + // Prank the order's seller + vm.startPrank(seller); + + // Execute the cancel + dex.cancelSellOrder(orderId); + } + + function cancelBatchSellOrder( + uint256[] memory orderIds, + uint256 actorIndexSeed + ) public useActor(actorIndexSeed) { + // Bound the input length to a reasonable limit + uint256 len = bound(orderIds.length, 0, MAX_BATCH_CANCEL_SELL_ORDER); + + // Create new orders if the order does not exist or the seller is not the current actor + uint256[] memory _newOrderIds = new uint256[](len); + for (uint256 i; i < len; ++i) { + IOrderbookDex.Order memory order = dex.getOrder(orderIds[i]); + if (order.assetAmount == 0 || order.seller != currentActor) { + uint256 x = uint256(keccak256(abi.encodePacked(i))); + _newOrderIds[i] = this.createSellOrder(x, x, x, actorIndexSeed); + } else { + _newOrderIds[i] = orderIds[i]; + } + } + + // If this.createSellOrder was called, the prank was stopped, so we need to start it again + if (len > 0) { + vm.startPrank(currentActor); + } + + // Execute the batch cancel + dex.cancelBatchSellOrder(_newOrderIds); + } + + fallback() external payable {} +} + +contract OrderbookDexInvariantTest is CTest, ERC1155Holder { + using Address for address payable; + + CheatCodes vm = CheatCodes(HEVM_ADDRESS); + OrderbookDex public dex; + OrderbookDexHandler public dexHandler; + IInverseAppProjected1155 asset; + AssetHandler public assetHandler; + + function setUp() public { + asset = new InverseAppProjected1155("Gold", "GOLD", address(this)); + dex = new OrderbookDex(address(asset)); + dexHandler = new OrderbookDexHandler(asset, dex); + assetHandler = new AssetHandler(asset, dex); + targetContract(address(assetHandler)); + targetContract(address(dexHandler)); + } + + function invariant_ordersAssetAmountEqualsContractTokenBalance() public { + for (uint256 i; i < dex.currentOrderId(); ++i) { + IOrderbookDex.Order memory order = dex.getOrder(i); + assertEq(order.assetAmount, asset.balanceOf(address(dex), order.assetId)); + } + } + + function invariant_contractDoesNotObtainEther() public { + assertEq(address(dex).balance, 0); + } + + function invariant_orderIdIsIncremental() public { + uint256 currentId = dex.currentOrderId(); + uint256 previousId = dexHandler.previousOrderId(); + if (currentId == previousId) { + assertEq(currentId, 0); + return; + } + assertGe(currentId, previousId); + } + + receive() external payable {} +}