diff --git a/contracts/OrderLib.sol b/contracts/OrderLib.sol index c9114b21..a489be8c 100644 --- a/contracts/OrderLib.sol +++ b/contracts/OrderLib.sol @@ -9,12 +9,13 @@ import "./interfaces/IOrderMixin.sol"; import "./libraries/MakerTraitsLib.sol"; import "./libraries/ExtensionLib.sol"; import "./helpers/AmountCalculator.sol"; +import "./interfaces/IAmountGetter.sol"; /** * @title OrderLib - * @dev The library provides common functionality for processing and manipulating limit orders. - * It provides functionality to calculate and verify order hashes, calculate trade amounts, and validate - * extension data associated with orders. The library also contains helper methods to get the receiver of + * @dev The library provides common functionality for processing and manipulating limit orders. + * It provides functionality to calculate and verify order hashes, calculate trade amounts, and validate + * extension data associated with orders. The library also contains helper methods to get the receiver of * an order and call getter functions. */ library OrderLib { @@ -78,7 +79,7 @@ import "./helpers/AmountCalculator.sol"; return receiver != address(0) ? receiver : order.maker.get(); } - /** + /** * @notice Calculates the making amount based on the requested taking amount. * @dev If getter is specified in the extension data, the getter is called to calculate the making amount, * otherwise the making amount is calculated linearly. @@ -96,12 +97,20 @@ import "./helpers/AmountCalculator.sol"; uint256 remainingMakingAmount, bytes32 orderHash ) internal view returns(uint256) { - bytes calldata getter = extension.makingAmountGetter(); - if (getter.length == 0) { + bytes calldata data = extension.makingAmountData(); + if (data.length == 0) { // Linear proportion return AmountCalculator.getMakingAmount(order.makingAmount, order.takingAmount, requestedTakingAmount); } - return _callGetter(getter, requestedTakingAmount, remainingMakingAmount, orderHash); + return IAmountGetter(address(bytes20(data))).getMakingAmount( + order, + extension, + orderHash, + msg.sender, + requestedTakingAmount, + remainingMakingAmount, + data[20:] + ); } /** @@ -122,33 +131,20 @@ import "./helpers/AmountCalculator.sol"; uint256 remainingMakingAmount, bytes32 orderHash ) internal view returns(uint256) { - bytes calldata getter = extension.takingAmountGetter(); - if (getter.length == 0) { + bytes calldata data = extension.takingAmountData(); + if (data.length == 0) { // Linear proportion return AmountCalculator.getTakingAmount(order.makingAmount, order.takingAmount, requestedMakingAmount); } - return _callGetter(getter, requestedMakingAmount, remainingMakingAmount, orderHash); - } - - /** - * @notice Calls the getter function to calculate an amount for a trade. - * @param getter The address of the getter function. - * @param requestedAmount The amount requested by the taker. - * @param remainingMakingAmount The remaining amount of the asset left to fill. - * @param orderHash The hash of the order. - * @return amount The calculated amount. - */ - function _callGetter( - bytes calldata getter, - uint256 requestedAmount, - uint256 remainingMakingAmount, - bytes32 orderHash - ) private view returns(uint256) { - if (getter.length < 20) revert WrongGetter(); - - (bool success, bytes memory result) = address(bytes20(getter)).staticcall(abi.encodePacked(getter[20:], requestedAmount, remainingMakingAmount, orderHash)); - if (!success || result.length != 32) revert GetAmountCallFailed(); - return abi.decode(result, (uint256)); + return IAmountGetter(address(bytes20(data))).getTakingAmount( + order, + extension, + orderHash, + msg.sender, + requestedMakingAmount, + remainingMakingAmount, + data[20:] + ); } /** diff --git a/contracts/OrderMixin.sol b/contracts/OrderMixin.sol index aac1fdc7..4b2f0acb 100644 --- a/contracts/OrderMixin.sol +++ b/contracts/OrderMixin.sol @@ -375,7 +375,7 @@ abstract contract OrderMixin is IOrderMixin, EIP712, OnlyWethReceiver, Predicate data = data[20:]; } IPreInteraction(listener).preInteraction( - order, orderHash, msg.sender, makingAmount, takingAmount, remainingMakingAmount, data + order, extension, orderHash, msg.sender, makingAmount, takingAmount, remainingMakingAmount, data ); } @@ -403,7 +403,7 @@ abstract contract OrderMixin is IOrderMixin, EIP712, OnlyWethReceiver, Predicate if (interaction.length >= 20) { // proceed only if interaction length is enough to store address uint256 offeredTakingAmount = ITakerInteraction(address(bytes20(interaction))).takerInteraction( - order, orderHash, extension, msg.sender, makingAmount, takingAmount, remainingMakingAmount, interaction[20:] + order, extension, orderHash, msg.sender, makingAmount, takingAmount, remainingMakingAmount, interaction[20:] ); if (offeredTakingAmount > takingAmount && order.makerTraits.allowImproveRateViaInteraction()) { takingAmount = offeredTakingAmount; @@ -461,7 +461,7 @@ abstract contract OrderMixin is IOrderMixin, EIP712, OnlyWethReceiver, Predicate data = data[20:]; } IPostInteraction(listener).postInteraction( - order, orderHash, msg.sender, makingAmount, takingAmount, remainingMakingAmount, data + order, extension, orderHash, msg.sender, makingAmount, takingAmount, remainingMakingAmount, data ); } diff --git a/contracts/helpers/ChainlinkCalculator.sol b/contracts/helpers/ChainlinkCalculator.sol index 3cc08638..c6b85939 100644 --- a/contracts/helpers/ChainlinkCalculator.sol +++ b/contracts/helpers/ChainlinkCalculator.sol @@ -4,33 +4,63 @@ pragma solidity 0.8.19; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; import "@openzeppelin/contracts/utils/math/SafeCast.sol"; - +import "../interfaces/IOrderMixin.sol"; +import "../interfaces/IAmountGetter.sol"; /// @title A helper contract for interactions with https://docs.chain.link -contract ChainlinkCalculator { +contract ChainlinkCalculator is IAmountGetter { using SafeCast for int256; error DifferentOracleDecimals(); uint256 private constant _SPREAD_DENOMINATOR = 1e9; - uint256 private constant _INVERSE_MASK = 1 << 255; - - /// @notice Calculates price of token relative to oracle unit (ETH or USD) - /// @param inverseAndSpread concatenated inverse flag and spread. - /// Lowest 254 bits specify spread amount. Spread is scaled by 1e9, i.e. 101% = 1.01e9, 99% = 0.99e9. - /// Highest bit is set when oracle price should be inverted, - /// e.g. for DAI-ETH oracle, inverse=false means that we request DAI price in ETH - /// and inverse=true means that we request ETH price in DAI - /// @return Amount * spread * oracle price - function singlePrice(AggregatorV3Interface oracle, uint256 inverseAndSpread, uint256 amount) external view returns(uint256) { + + function getMakingAmount( + IOrderMixin.Order calldata /* order */, + bytes calldata /* extension */, + bytes32 /* orderHash */, + address /* taker */, + uint256 takingAmount, + uint256 /* remainingMakingAmount */, + bytes calldata extraData + ) external view returns (uint256) { + ( + AggregatorV3Interface oracle, + uint256 spread + ) = abi.decode(extraData, (AggregatorV3Interface, uint256)); + + /// @notice Calculates price of token relative to oracle unit (ETH or USD) + /// Lowest 254 bits specify spread amount. Spread is scaled by 1e9, i.e. 101% = 1.01e9, 99% = 0.99e9. + /// Highest bit is set when oracle price should be inverted, + /// e.g. for DAI-ETH oracle, inverse=false means that we request DAI price in ETH + /// and inverse=true means that we request ETH price in DAI + /// @return Amount * spread * oracle price (, int256 latestAnswer,,,) = oracle.latestRoundData(); - bool inverse = inverseAndSpread & _INVERSE_MASK > 0; - uint256 spread = inverseAndSpread & (~_INVERSE_MASK); - if (inverse) { - return amount * spread * (10 ** oracle.decimals()) / latestAnswer.toUint256() / _SPREAD_DENOMINATOR; - } else { - return amount * spread * latestAnswer.toUint256() / (10 ** oracle.decimals()) / _SPREAD_DENOMINATOR; - } + return takingAmount * spread * latestAnswer.toUint256() / (10 ** oracle.decimals()) / _SPREAD_DENOMINATOR; + } + + function getTakingAmount( + IOrderMixin.Order calldata /* order */, + bytes calldata /* extension */, + bytes32 /* orderHash */, + address /* taker */, + uint256 makingAmount, + uint256 /* remainingMakingAmount */, + bytes calldata extraData + ) external view returns (uint256) { + ( + AggregatorV3Interface oracle, + uint256 spread + ) = abi.decode(extraData, (AggregatorV3Interface, uint256)); + + /// @notice Calculates price of token relative to oracle unit (ETH or USD) + /// Lowest 254 bits specify spread amount. Spread is scaled by 1e9, i.e. 101% = 1.01e9, 99% = 0.99e9. + /// Highest bit is set when oracle price should be inverted, + /// e.g. for DAI-ETH oracle, inverse=false means that we request DAI price in ETH + /// and inverse=true means that we request ETH price in DAI + /// @return Amount * spread * oracle price + (, int256 latestAnswer,,,) = oracle.latestRoundData(); + return makingAmount * spread * (10 ** oracle.decimals()) / latestAnswer.toUint256() / _SPREAD_DENOMINATOR; } /// @notice Calculates price of token A relative to token B. Note that order is important diff --git a/contracts/helpers/DutchAuctionCalculator.sol b/contracts/helpers/DutchAuctionCalculator.sol index f1fbc803..f331b88a 100644 --- a/contracts/helpers/DutchAuctionCalculator.sol +++ b/contracts/helpers/DutchAuctionCalculator.sol @@ -3,18 +3,49 @@ pragma solidity 0.8.19; import "@openzeppelin/contracts/utils/math/Math.sol"; +import "../interfaces/IAmountGetter.sol"; + +contract DutchAuctionCalculator is IAmountGetter { + using Math for uint256; -contract DutchAuctionCalculator { uint256 private constant _LOW_128_BITS = 0xffffffffffffffffffffffffffffffff; - function getMakingAmount(uint256 startTimeEndTime, uint256 takingAmountStart, uint256 takingAmountEnd, uint256 makingAmount, uint256 requestedTakingAmount) external view returns(uint256) { + function getMakingAmount( + IOrderMixin.Order calldata order, + bytes calldata /* extension */, + bytes32 /* orderHash */, + address /* taker */, + uint256 takingAmount, + uint256 /* remainingMakingAmount */, + bytes calldata extraData + ) external view returns (uint256) { + ( + uint256 startTimeEndTime, + uint256 takingAmountStart, + uint256 takingAmountEnd + ) = abi.decode(extraData, (uint256, uint256, uint256)); + uint256 calculatedTakingAmount = _calculateAuctionTakingAmount(startTimeEndTime, takingAmountStart, takingAmountEnd); - return requestedTakingAmount * makingAmount / calculatedTakingAmount; + return order.makingAmount * takingAmount / calculatedTakingAmount; } - function getTakingAmount(uint256 startTimeEndTime, uint256 takingAmountStart, uint256 takingAmountEnd, uint256 makingAmount, uint256 requestedMakingAmount) external view returns(uint256) { + function getTakingAmount( + IOrderMixin.Order calldata order, + bytes calldata /* extension */, + bytes32 /* orderHash */, + address /* taker */, + uint256 makingAmount, + uint256 /* remainingMakingAmount */, + bytes calldata extraData + ) external view returns (uint256) { + ( + uint256 startTimeEndTime, + uint256 takingAmountStart, + uint256 takingAmountEnd + ) = abi.decode(extraData, (uint256, uint256, uint256)); + uint256 calculatedTakingAmount = _calculateAuctionTakingAmount(startTimeEndTime, takingAmountStart, takingAmountEnd); - return (requestedMakingAmount * calculatedTakingAmount + makingAmount - 1) / makingAmount; + return (calculatedTakingAmount * makingAmount).ceilDiv(order.makingAmount); } function _calculateAuctionTakingAmount(uint256 startTimeEndTime, uint256 takingAmountStart, uint256 takingAmountEnd) private view returns(uint256) { diff --git a/contracts/helpers/ETHOrders.sol b/contracts/helpers/ETHOrders.sol index 1dbb6e01..3352e24a 100644 --- a/contracts/helpers/ETHOrders.sol +++ b/contracts/helpers/ETHOrders.sol @@ -111,6 +111,7 @@ contract ETHOrders is IPostInteraction, OnlyWethReceiver { */ function postInteraction( IOrderMixin.Order calldata /*order*/, + bytes calldata /* extension */, bytes32 orderHash, address /*taker*/, uint256 makingAmount, diff --git a/contracts/helpers/OrderIdInvalidator.sol b/contracts/helpers/OrderIdInvalidator.sol index 7bc66e06..4c42cacc 100644 --- a/contracts/helpers/OrderIdInvalidator.sol +++ b/contracts/helpers/OrderIdInvalidator.sol @@ -33,6 +33,7 @@ contract OrderIdInvalidator is IPreInteraction { function preInteraction( IOrderMixin.Order calldata order, + bytes calldata /* extension */, bytes32 orderHash, address /* taker */, uint256 /* makingAmount */, diff --git a/contracts/helpers/RangeAmountCalculator.sol b/contracts/helpers/RangeAmountCalculator.sol index e16f9b4d..4fed9c82 100644 --- a/contracts/helpers/RangeAmountCalculator.sol +++ b/contracts/helpers/RangeAmountCalculator.sol @@ -3,6 +3,8 @@ pragma solidity 0.8.19; import "@openzeppelin/contracts/utils/math/Math.sol"; +import "../interfaces/IOrderMixin.sol"; +import "../interfaces/IAmountGetter.sol"; /** * A range limit order is a strategy used to sell an asset within a specified price range. @@ -20,8 +22,7 @@ import "@openzeppelin/contracts/utils/math/Math.sol"; * y = ----------------------- * x + priceStart * totalAmount */ -contract RangeAmountCalculator { - +contract RangeAmountCalculator is IAmountGetter { error IncorrectRange(); modifier correctPrices(uint256 priceStart, uint256 priceEnd) { @@ -29,14 +30,46 @@ contract RangeAmountCalculator { _; } + function getTakingAmount( + IOrderMixin.Order calldata order, + bytes calldata /* extension */, + bytes32 /* orderHash */, + address /* taker */, + uint256 makingAmount, + uint256 remainingMakingAmount, + bytes calldata extraData + ) external pure returns (uint256) { + ( + uint256 priceStart, + uint256 priceEnd + ) = abi.decode(extraData, (uint256, uint256)); + return getRangeTakerAmount(priceStart, priceEnd, order.makingAmount, makingAmount, remainingMakingAmount); + } + + function getMakingAmount( + IOrderMixin.Order calldata order, + bytes calldata /* extension */, + bytes32 /* orderHash */, + address /* taker */, + uint256 takingAmount, + uint256 remainingMakingAmount, + bytes calldata extraData + ) external pure returns (uint256) { + ( + uint256 priceStart, + uint256 priceEnd + ) = abi.decode(extraData, (uint256, uint256)); + return getRangeMakerAmount(priceStart, priceEnd, order.makingAmount, takingAmount, remainingMakingAmount); + } + function getRangeTakerAmount( uint256 priceStart, uint256 priceEnd, - uint256 totalAmount, - uint256 fillAmount, + uint256 orderMakingAmount, + uint256 makingAmount, uint256 remainingMakingAmount ) public correctPrices(priceStart, priceEnd) pure returns(uint256) { - uint256 alreadyFilledMakingAmount = totalAmount - remainingMakingAmount; + uint256 alreadyFilledMakingAmount = orderMakingAmount - remainingMakingAmount; /** * rangeTakerAmount = ( * f(makerAmountFilled) + f(makerAmountFilled + fillAmount) @@ -45,22 +78,22 @@ contract RangeAmountCalculator { * scaling to 1e18 happens to have better price accuracy */ return ( - (priceEnd - priceStart) * (2 * alreadyFilledMakingAmount + fillAmount) / totalAmount + + (priceEnd - priceStart) * (2 * alreadyFilledMakingAmount + makingAmount) / orderMakingAmount + 2 * priceStart - ) * fillAmount / 2e18; + ) * makingAmount / 2e18; } function getRangeMakerAmount( uint256 priceStart, uint256 priceEnd, - uint256 totalLiquidity, + uint256 orderMakingAmount, uint256 takingAmount, uint256 remainingMakingAmount ) public correctPrices(priceStart, priceEnd) pure returns(uint256) { - uint256 alreadyFilledMakingAmount = totalLiquidity - remainingMakingAmount; + uint256 alreadyFilledMakingAmount = orderMakingAmount - remainingMakingAmount; uint256 b = priceStart; - uint256 k = (priceEnd - priceStart) * 1e18 / totalLiquidity; - uint256 bDivK = priceStart * totalLiquidity / (priceEnd - priceStart); + uint256 k = (priceEnd - priceStart) * 1e18 / orderMakingAmount; + uint256 bDivK = priceStart * orderMakingAmount / (priceEnd - priceStart); return (Math.sqrt( ( b * bDivK + diff --git a/contracts/interfaces/IAmountGetter.sol b/contracts/interfaces/IAmountGetter.sol new file mode 100644 index 00000000..04e23db5 --- /dev/null +++ b/contracts/interfaces/IAmountGetter.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./IOrderMixin.sol"; + +interface IAmountGetter { + /** + * @notice View method that gets called to determine the actual making amount + * @param order Order being processed + * @param extension Order extension data + * @param orderHash Hash of the order being processed + * @param taker Taker address + * @param takingAmount Actual taking amount + * @param remainingMakingAmount Order remaining making amount + * @param extraData Extra data + */ + function getMakingAmount( + IOrderMixin.Order calldata order, + bytes calldata extension, + bytes32 orderHash, + address taker, + uint256 takingAmount, + uint256 remainingMakingAmount, + bytes calldata extraData + ) external view returns (uint256); + + /** + * @notice View method that gets called to determine the actual making amount + * @param order Order being processed + * @param extension Order extension data + * @param orderHash Hash of the order being processed + * @param taker Taker address + * @param makingAmount Actual taking amount + * @param remainingMakingAmount Order remaining making amount + * @param extraData Extra data + */ + function getTakingAmount( + IOrderMixin.Order calldata order, + bytes calldata extension, + bytes32 orderHash, + address taker, + uint256 makingAmount, + uint256 remainingMakingAmount, + bytes calldata extraData + ) external view returns (uint256); +} diff --git a/contracts/interfaces/IPostInteraction.sol b/contracts/interfaces/IPostInteraction.sol index d45ab789..9b7b37e4 100644 --- a/contracts/interfaces/IPostInteraction.sol +++ b/contracts/interfaces/IPostInteraction.sol @@ -8,6 +8,7 @@ interface IPostInteraction { /** * @notice Callback method that gets called after all fund transfers * @param order Order being processed + * @param extension Order extension data * @param orderHash Hash of the order being processed * @param taker Taker address * @param makingAmount Actual making amount @@ -17,6 +18,7 @@ interface IPostInteraction { */ function postInteraction( IOrderMixin.Order calldata order, + bytes calldata extension, bytes32 orderHash, address taker, uint256 makingAmount, diff --git a/contracts/interfaces/IPreInteraction.sol b/contracts/interfaces/IPreInteraction.sol index a88a894b..4bbe99eb 100644 --- a/contracts/interfaces/IPreInteraction.sol +++ b/contracts/interfaces/IPreInteraction.sol @@ -8,6 +8,7 @@ interface IPreInteraction { /** * @notice Callback method that gets called before any funds transfers * @param order Order being processed + * @param extension Order extension data * @param orderHash Hash of the order being processed * @param taker Taker address * @param makingAmount Actual making amount @@ -17,6 +18,7 @@ interface IPreInteraction { */ function preInteraction( IOrderMixin.Order calldata order, + bytes calldata extension, bytes32 orderHash, address taker, uint256 makingAmount, diff --git a/contracts/interfaces/ITakerInteraction.sol b/contracts/interfaces/ITakerInteraction.sol index e71d7a67..94d164fd 100644 --- a/contracts/interfaces/ITakerInteraction.sol +++ b/contracts/interfaces/ITakerInteraction.sol @@ -13,8 +13,8 @@ interface ITakerInteraction { * @dev This callback allows to interactively handle maker aseets to produce takers assets, doesn't supports ETH as taker assets * @notice Callback method that gets called after maker fund transfer but before taker fund transfer * @param order Order being processed + * @param extension Order extension data * @param orderHash Hash of the order being processed - * @param extension Extension data * @param taker Taker address * @param makingAmount Actual making amount * @param takingAmount Actual taking amount @@ -23,8 +23,8 @@ interface ITakerInteraction { */ function takerInteraction( IOrderMixin.Order calldata order, - bytes32 orderHash, bytes calldata extension, + bytes32 orderHash, address taker, uint256 makingAmount, uint256 takingAmount, diff --git a/contracts/libraries/ExtensionLib.sol b/contracts/libraries/ExtensionLib.sol index b6670093..120a9f42 100644 --- a/contracts/libraries/ExtensionLib.sol +++ b/contracts/libraries/ExtensionLib.sol @@ -16,8 +16,8 @@ library ExtensionLib { enum DynamicField { MakerAssetSuffix, TakerAssetSuffix, - MakingAmountGetter, - TakingAmountGetter, + MakingAmountData, + TakingAmountData, Predicate, MakerPermit, PreInteractionData, @@ -44,21 +44,21 @@ library ExtensionLib { } /** - * @notice Returns the MakingAmountGetter from the provided extension calldata. - * @param extension The calldata from which the MakingAmountGetter is to be retrieved. - * @return calldata Bytes representing the MakingAmountGetter. + * @notice Returns the MakingAmountData from the provided extension calldata. + * @param extension The calldata from which the MakingAmountData is to be retrieved. + * @return calldata Bytes representing the MakingAmountData. */ - function makingAmountGetter(bytes calldata extension) internal pure returns(bytes calldata) { - return _get(extension, DynamicField.MakingAmountGetter); + function makingAmountData(bytes calldata extension) internal pure returns(bytes calldata) { + return _get(extension, DynamicField.MakingAmountData); } /** - * @notice Returns the TakingAmountGetter from the provided extension calldata. - * @param extension The calldata from which the TakingAmountGetter is to be retrieved. - * @return calldata Bytes representing the TakingAmountGetter. + * @notice Returns the TakingAmountData from the provided extension calldata. + * @param extension The calldata from which the TakingAmountData is to be retrieved. + * @return calldata Bytes representing the TakingAmountData. */ - function takingAmountGetter(bytes calldata extension) internal pure returns(bytes calldata) { - return _get(extension, DynamicField.TakingAmountGetter); + function takingAmountData(bytes calldata extension) internal pure returns(bytes calldata) { + return _get(extension, DynamicField.TakingAmountData); } /** diff --git a/contracts/mocks/HashChecker.sol b/contracts/mocks/HashChecker.sol index 8bb0a634..141ec5c8 100644 --- a/contracts/mocks/HashChecker.sol +++ b/contracts/mocks/HashChecker.sol @@ -28,6 +28,7 @@ contract HashChecker is IPreInteraction, Ownable { function preInteraction( IOrderMixin.Order calldata order, + bytes calldata extension, bytes32 orderHash, address taker, uint256 makingAmount, @@ -40,6 +41,7 @@ contract HashChecker is IPreInteraction, Ownable { if (extraData.length != 0) { IPreInteraction(address(bytes20(extraData))).preInteraction( order, + extension, orderHash, taker, makingAmount, diff --git a/contracts/mocks/InteractionMock.sol b/contracts/mocks/InteractionMock.sol index d6bfc834..6abd62e3 100644 --- a/contracts/mocks/InteractionMock.sol +++ b/contracts/mocks/InteractionMock.sol @@ -16,6 +16,7 @@ contract InteractionMock is IPreInteraction, IPostInteraction, ITakerInteraction function preInteraction( IOrderMixin.Order calldata /* order */, + bytes calldata /* extension */, bytes32 /* orderHash */, address /* taker */, uint256 /* makingAmount */, @@ -35,6 +36,7 @@ contract InteractionMock is IPreInteraction, IPostInteraction, ITakerInteraction function postInteraction( IOrderMixin.Order calldata /* order */, + bytes calldata /* extension */, bytes32 /* orderHash */, address /* taker */, uint256 /* makingAmount */, @@ -54,8 +56,8 @@ contract InteractionMock is IPreInteraction, IPostInteraction, ITakerInteraction function takerInteraction( IOrderMixin.Order calldata /* order */, - bytes32 /* orderHash */, bytes calldata /* extension */, + bytes32 /* orderHash */, address /* taker */, uint256 /* makingAmount */, uint256 takingAmount, diff --git a/contracts/mocks/RecursiveMatcher.sol b/contracts/mocks/RecursiveMatcher.sol index 7d44160e..83182142 100644 --- a/contracts/mocks/RecursiveMatcher.sol +++ b/contracts/mocks/RecursiveMatcher.sol @@ -36,8 +36,8 @@ contract RecursiveMatcher is ITakerInteraction { function takerInteraction( IOrderMixin.Order calldata /* order */, - bytes32 /* orderHash */, bytes calldata /* extension */, + bytes32 /* orderHash */, address /* taker */, uint256 /* makingAmount */, uint256 /* takingAmount */, diff --git a/contracts/mocks/TakerIncreaser.sol b/contracts/mocks/TakerIncreaser.sol index 7b45f47f..429fe9ea 100644 --- a/contracts/mocks/TakerIncreaser.sol +++ b/contracts/mocks/TakerIncreaser.sol @@ -33,8 +33,8 @@ contract TakerIncreaser is ITakerInteraction { function takerInteraction( IOrderMixin.Order calldata /* order */, - bytes32 /* orderHash */, bytes calldata /* extension */, + bytes32 /* orderHash */, address /* taker */, uint256 /* makingAmount */, uint256 takingAmount, diff --git a/test/ChainLinkExample.js b/test/ChainLinkExample.js index d0e274a8..5ef93924 100644 --- a/test/ChainLinkExample.js +++ b/test/ChainLinkExample.js @@ -1,7 +1,7 @@ -const { expect, trim0x } = require('@1inch/solidity-utils'); +const { expect } = require('@1inch/solidity-utils'); const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); const { fillWithMakingAmount, signOrder, buildOrder } = require('./helpers/orderUtils'); -const { cutLastArg, ether, setn } = require('./helpers/utils'); +const { ether } = require('./helpers/utils'); const { deploySwapTokens } = require('./helpers/fixtures'); const { ethers } = require('hardhat'); @@ -12,18 +12,6 @@ describe('ChainLinkExample', function () { [addr, addr1] = await ethers.getSigners(); }); - function buildInverseWithSpread (inverse, spread) { - return setn(spread, 255, inverse).toString(); - } - - function buildSinglePriceGetter (chainlink, oracle, inverse, spread, amount = '0') { - return chainlink.address + trim0x(chainlink.interface.encodeFunctionData('singlePrice', [oracle.address, buildInverseWithSpread(inverse, spread), amount])); - } - - function buildDoublePriceGetter (chainlink, oracle1, oracle2, spread, amount = '0') { - return chainlink.address + trim0x(chainlink.interface.encodeFunctionData('doublePrice', [oracle1.address, oracle2.address, buildInverseWithSpread(false, spread), '0', amount])); - } - async function deployContractsAndInit () { const { dai, weth, inch, swap, chainId } = await deploySwapTokens(); @@ -67,8 +55,8 @@ describe('ChainLinkExample', function () { maker: addr1.address, }, { - makingAmountGetter: cutLastArg(buildSinglePriceGetter(chainlink, daiOracle, false, '990000000')), // maker offset is 0.99 - takingAmountGetter: cutLastArg(buildSinglePriceGetter(chainlink, daiOracle, true, '1010000000')), // taker offset is 1.01 + makingAmountData: ethers.utils.solidityPack(['address', 'uint256', 'uint256'], [chainlink.address, daiOracle.address, '990000000']), // maker offset is 0.99 + takingAmountData: ethers.utils.solidityPack(['address', 'uint256', 'uint256'], [chainlink.address, daiOracle.address, '1010000000']), // taker offset is 1.01 }, ); @@ -88,7 +76,7 @@ describe('ChainLinkExample', function () { const takingAmount = ether('631'); const priceCall = swap.interface.encodeFunctionData('arbitraryStaticCall', [ chainlink.address, - chainlink.interface.encodeFunctionData('doublePrice', [inchOracle.address, daiOracle.address, buildInverseWithSpread(false, '1000000000'), '0', ether('1')]), + chainlink.interface.encodeFunctionData('doublePrice', [inchOracle.address, daiOracle.address, '1000000000', '0', ether('1')]), ]); const order = buildOrder( @@ -116,7 +104,7 @@ describe('ChainLinkExample', function () { const makingAmount = ether('100'); const takingAmount = ether('631'); - const priceCall = buildDoublePriceGetter(chainlink, inchOracle, daiOracle, '1000000000', ether('1')); + const priceCall = chainlink.interface.encodeFunctionData('doublePrice', [inchOracle.address, daiOracle.address, '1000000000', '0', ether('1')]); const order = buildOrder( { diff --git a/test/DutchAuctionCalculator.js b/test/DutchAuctionCalculator.js index b16df7fe..a39ab3bd 100644 --- a/test/DutchAuctionCalculator.js +++ b/test/DutchAuctionCalculator.js @@ -1,6 +1,6 @@ -const { expect, trim0x, time, assertRoughlyEqualValues } = require('@1inch/solidity-utils'); +const { expect, time, assertRoughlyEqualValues } = require('@1inch/solidity-utils'); const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); -const { cutLastArg, ether } = require('./helpers/utils'); +const { ether } = require('./helpers/utils'); const { deploySwapTokens } = require('./helpers/fixtures'); const { fillWithMakingAmount, buildOrder, signOrder } = require('./helpers/orderUtils'); const { ethers } = require('hardhat'); @@ -40,12 +40,14 @@ describe('Dutch auction', function () { maker: addr.address, }, { - makingAmountGetter: dutchAuctionCalculator.address + cutLastArg(trim0x(dutchAuctionCalculator.interface.encodeFunctionData('getMakingAmount', - [startEndTs.toString(), ether('0.1'), ether('0.05'), ether('100'), 0], - )), 64), - takingAmountGetter: dutchAuctionCalculator.address + cutLastArg(trim0x(dutchAuctionCalculator.interface.encodeFunctionData('getTakingAmount', - [startEndTs.toString(), ether('0.1'), ether('0.05'), ether('100'), 0], - )), 64), + makingAmountData: ethers.utils.solidityPack( + ['address', 'uint256', 'uint256', 'uint256'], + [dutchAuctionCalculator.address, startEndTs.toString(), ether('0.1'), ether('0.05')], + ), + takingAmountData: ethers.utils.solidityPack( + ['address', 'uint256', 'uint256', 'uint256'], + [dutchAuctionCalculator.address, startEndTs.toString(), ether('0.1'), ether('0.05')], + ), }, ); const signature = await signOrder(order, chainId, swap.address, addr); diff --git a/test/LimitOrderProtocol.js b/test/LimitOrderProtocol.js index 8d1b6344..d70a3684 100644 --- a/test/LimitOrderProtocol.js +++ b/test/LimitOrderProtocol.js @@ -541,7 +541,7 @@ describe('LimitOrderProtocol', function () { return { dai, weth, swap, chainId }; }; - it('empty takingAmountGetter should work on full fill', async function () { + it('empty takingAmountData should work on full fill', async function () { const { dai, weth, swap, chainId } = await loadFixture(deployContractsAndInit); const order = buildOrder({ @@ -559,7 +559,7 @@ describe('LimitOrderProtocol', function () { await expect(filltx).to.changeTokenBalances(weth, [addr, addr1], [-10, 10]); }); - it('empty takingAmountGetter should revert on partial fill', async function () { + it('empty takingAmountData should revert on partial fill', async function () { const { dai, weth, swap, chainId } = await loadFixture(deployContractsAndInit); const order = buildOrder({ @@ -576,7 +576,7 @@ describe('LimitOrderProtocol', function () { .to.be.revertedWithCustomError(swap, 'PartialFillNotAllowed'); }); - it('empty makingAmountGetter should revert on partial fill', async function () { + it('empty makingAmountData should revert on partial fill', async function () { const { dai, weth, swap, chainId } = await loadFixture(deployContractsAndInit); const order = buildOrder({ @@ -593,7 +593,7 @@ describe('LimitOrderProtocol', function () { .to.be.revertedWithCustomError(swap, 'PartialFillNotAllowed'); }); - it('empty makingAmountGetter should work on full fill', async function () { + it('empty makingAmountData should work on full fill', async function () { const { dai, weth, swap, chainId } = await loadFixture(deployContractsAndInit); const order = buildOrder({ diff --git a/test/RangeLimitOrders.js b/test/RangeLimitOrders.js index 5e052513..c69a4344 100644 --- a/test/RangeLimitOrders.js +++ b/test/RangeLimitOrders.js @@ -1,9 +1,9 @@ const { ethers } = require('hardhat'); const { parseUnits } = require('ethers/lib/utils.js'); const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); -const { expect, trim0x } = require('@1inch/solidity-utils'); +const { expect } = require('@1inch/solidity-utils'); const { fillWithMakingAmount, buildMakerTraits, buildOrder, signOrder } = require('./helpers/orderUtils'); -const { cutLastArg, ether } = require('./helpers/utils'); +const { ether } = require('./helpers/utils'); const { deploySwapTokens, deployRangeAmountCalculator } = require('./helpers/fixtures'); describe('RangeLimitOrders', function () { @@ -64,12 +64,14 @@ describe('RangeLimitOrders', function () { maker: maker.address, makerTraits: buildMakerTraits({ allowMultipleFills: true }), }, { - makingAmountGetter: rangeAmountCalculator.address + trim0x(cutLastArg(cutLastArg( - rangeAmountCalculator.interface.encodeFunctionData('getRangeMakerAmount', [startPrice, endPrice, makingAmount, 0, 0], 64), - ))), - takingAmountGetter: rangeAmountCalculator.address + trim0x(cutLastArg(cutLastArg( - rangeAmountCalculator.interface.encodeFunctionData('getRangeTakerAmount', [startPrice, endPrice, makingAmount, 0, 0], 64), - ))), + makingAmountData: ethers.utils.solidityPack( + ['address', 'uint256', 'uint256'], + [rangeAmountCalculator.address, startPrice, endPrice], + ), + takingAmountData: ethers.utils.solidityPack( + ['address', 'uint256', 'uint256'], + [rangeAmountCalculator.address, startPrice, endPrice], + ), }); const signature = await signOrder(order, chainId, swap.address, maker); const { r, _vs: vs } = ethers.utils.splitSignature(signature); diff --git a/test/examples/LimitOrderProtocol-example.js b/test/examples/LimitOrderProtocol-example.js index 1a1c0b1d..065f8d1f 100644 --- a/test/examples/LimitOrderProtocol-example.js +++ b/test/examples/LimitOrderProtocol-example.js @@ -1,9 +1,9 @@ const hre = require('hardhat'); const { ethers } = hre; -const { expect, time, constants, trim0x } = require('@1inch/solidity-utils'); +const { expect, time, constants } = require('@1inch/solidity-utils'); const { fillWithMakingAmount, buildMakerTraits, buildOrder, signOrder, ABIOrder } = require('../helpers/orderUtils'); const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); -const { joinStaticCalls, ether, cutLastArg } = require('../helpers/utils'); +const { joinStaticCalls, ether } = require('../helpers/utils'); describe.skip('LimitOrderProtocol usage example', function () { let addr, addr1, addr2; @@ -251,13 +251,15 @@ describe.skip('LimitOrderProtocol usage example', function () { const startPrice = ether('3000'); const endPrice = ether('4000'); - const makingAmountGetter = rangeAmountCalculator.address + trim0x(cutLastArg(cutLastArg( - rangeAmountCalculator.interface.encodeFunctionData('getRangeMakerAmount', [startPrice, endPrice, makingAmount, 0, 0], 64), - ))); + const makingAmountData = ethers.utils.solidityPack( + ['address', 'uint256', 'uint256'], + [rangeAmountCalculator.address, startPrice, endPrice], + ); - const takingAmountGetter = rangeAmountCalculator.address + trim0x(cutLastArg(cutLastArg( - rangeAmountCalculator.interface.encodeFunctionData('getRangeTakerAmount', [startPrice, endPrice, makingAmount, 0, 0], 64), - ))); + const takingAmountData = ethers.utils.solidityPack( + ['address', 'uint256', 'uint256'], + [rangeAmountCalculator.address, startPrice, endPrice], + ); // Build final order const order = buildOrder( @@ -269,8 +271,8 @@ describe.skip('LimitOrderProtocol usage example', function () { maker: addr1.address, makerTraits: buildMakerTraits({ allowMultipleFills: true }), }, { - makingAmountGetter, - takingAmountGetter, + makingAmountData, + takingAmountData, }, ); diff --git a/test/helpers/orderUtils.js b/test/helpers/orderUtils.js index bd0d2441..4d418255 100644 --- a/test/helpers/orderUtils.js +++ b/test/helpers/orderUtils.js @@ -100,8 +100,8 @@ function buildOrderRFQ ( { makerAssetSuffix = '0x', takerAssetSuffix = '0x', - makingAmountGetter = '0x', - takingAmountGetter = '0x', + makingAmountData = '0x', + takingAmountData = '0x', predicate = '0x', permit = '0x', preInteraction = '0x', @@ -126,8 +126,8 @@ function buildOrderRFQ ( { makerAssetSuffix, takerAssetSuffix, - makingAmountGetter, - takingAmountGetter, + makingAmountData, + takingAmountData, predicate, permit, preInteraction, @@ -149,8 +149,8 @@ function buildOrder ( { makerAssetSuffix = '0x', takerAssetSuffix = '0x', - makingAmountGetter = '0x', - takingAmountGetter = '0x', + makingAmountData = '0x', + takingAmountData = '0x', predicate = '0x', permit = '0x', preInteraction = '0x', @@ -161,8 +161,8 @@ function buildOrder ( const allInteractions = [ makerAssetSuffix, takerAssetSuffix, - makingAmountGetter, - takingAmountGetter, + makingAmountData, + takingAmountData, predicate, permit, preInteraction, diff --git a/test/helpers/utils.js b/test/helpers/utils.js index bbe242af..6f7b0bfd 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -66,10 +66,6 @@ function getSelector (data) { return data.substring(0, hexPrefix.length + 8); } -function cutLastArg (data, padding = 0) { - return data.substring(0, data.length - 64 - padding); -} - function joinStaticCalls (dataArray) { const trimmed = dataArray.map(trim0x); const cumulativeSum = (sum => value => { sum += value; return sum; })(0); @@ -99,7 +95,6 @@ module.exports = { price, ether, cutSelector, - cutLastArg, getSelector, setn, trim0x,