Skip to content

Commit

Permalink
Merge pull request #292 from 1inch/a/oz
Browse files Browse the repository at this point in the history
[SC-1010] OZ
  • Loading branch information
ZumZoom authored Dec 11, 2023
2 parents c454e0f + 29199d8 commit f3d2033
Show file tree
Hide file tree
Showing 13 changed files with 69 additions and 72 deletions.
24 changes: 13 additions & 11 deletions contracts/OrderMixin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,19 @@ abstract contract OrderMixin is IOrderMixin, EIP712, OnlyWethReceiver, Predicate
using BitInvalidatorLib for BitInvalidatorLib.Data;
using RemainingInvalidatorLib for RemainingInvalidator;

uint256 private constant _RAW_CALL_GAS_LIMIT = 5000;
address private constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;

IWETH private immutable _WETH; // solhint-disable-line var-name-mixedcase
mapping(address => BitInvalidatorLib.Data) private _bitInvalidator;
mapping(address => mapping(bytes32 => RemainingInvalidator)) private _remainingInvalidator;
mapping(address maker => BitInvalidatorLib.Data data) private _bitInvalidator;
mapping(address maker => mapping(bytes32 orderHash => RemainingInvalidator remaining)) private _remainingInvalidator;

constructor(IWETH weth) OnlyWethReceiver(address(weth)) {
_WETH = weth;
}

/**
* @notice See {IOrderMixin-permitAndCall}.
*/
function permitAndCall(bytes calldata permit, bytes calldata action) external {
IERC20(address(bytes20(permit))).tryPermit(msg.sender, address(this), permit[20:]);
IERC20(address(bytes20(permit))).tryPermit(permit[20:]);
// solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
let ptr := mload(0x40)
Expand Down Expand Up @@ -97,11 +97,12 @@ abstract contract OrderMixin is IOrderMixin, EIP712, OnlyWethReceiver, Predicate
*/
function cancelOrder(MakerTraits makerTraits, bytes32 orderHash) public {
if (makerTraits.useBitInvalidator()) {
_bitInvalidator[msg.sender].massInvalidate(makerTraits.nonceOrEpoch(), 0);
uint256 invalidator = _bitInvalidator[msg.sender].massInvalidate(makerTraits.nonceOrEpoch(), 0);
emit BitInvalidatorUpdated(msg.sender, makerTraits.nonceOrEpoch() >> 8, invalidator);
} else {
_remainingInvalidator[msg.sender][orderHash] = RemainingInvalidatorLib.fullyFilled();
emit OrderCancelled(orderHash);
}
emit OrderCancelled(orderHash);
}

/**
Expand All @@ -121,7 +122,8 @@ abstract contract OrderMixin is IOrderMixin, EIP712, OnlyWethReceiver, Predicate
*/
function bitsInvalidateForOrder(MakerTraits makerTraits, uint256 additionalMask) external {
if (!makerTraits.useBitInvalidator()) revert OrderIsNotSuitableForMassInvalidation();
_bitInvalidator[msg.sender].massInvalidate(makerTraits.nonceOrEpoch(), additionalMask);
uint256 invalidator = _bitInvalidator[msg.sender].massInvalidate(makerTraits.nonceOrEpoch(), additionalMask);
emit BitInvalidatorUpdated(msg.sender, makerTraits.nonceOrEpoch() >> 8, invalidator);
}

/**
Expand Down Expand Up @@ -404,14 +406,14 @@ abstract contract OrderMixin is IOrderMixin, EIP712, OnlyWethReceiver, Predicate
if (msg.value > takingAmount) {
unchecked {
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = msg.sender.call{value: msg.value - takingAmount, gas: _RAW_CALL_GAS_LIMIT}("");
(bool success, ) = msg.sender.call{value: msg.value - takingAmount}("");
if (!success) revert Errors.ETHTransferFailed();
}
}

if (order.makerTraits.unwrapWeth()) {
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = order.getReceiver().call{value: takingAmount, gas: _RAW_CALL_GAS_LIMIT}("");
(bool success, ) = order.getReceiver().call{value: takingAmount}("");
if (!success) revert Errors.ETHTransferFailed();
} else {
_WETH.safeDeposit(takingAmount);
Expand Down
4 changes: 4 additions & 0 deletions contracts/extensions/ChainlinkCalculator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "../interfaces/IOrderMixin.sol";
import "../interfaces/IAmountGetter.sol";

// solhint-disable not-rely-on-time

/// @title A helper contract for interactions with https://docs.chain.link
contract ChainlinkCalculator is IAmountGetter {
using SafeCast for int256;
Expand Down Expand Up @@ -91,3 +93,5 @@ contract ChainlinkCalculator is IAmountGetter {
}
}
}

// solhint-enable not-rely-on-time
2 changes: 1 addition & 1 deletion contracts/extensions/ETHOrders.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ contract ETHOrders is IPostInteraction, OnlyWethReceiver {
address private immutable _limitOrderProtocol;
IWETH private immutable _WETH; // solhint-disable-line var-name-mixedcase
/// @notice Makers and their uint96 ETH balances in single mapping.
mapping(bytes32 => ETHOrder) public ordersMakersBalances;
mapping(bytes32 orderHash => ETHOrder data) public ordersMakersBalances;

event ETHDeposited(bytes32 orderHash, uint256 amount);
event ETHOrderCancelled(bytes32 orderHash, uint256 amount);
Expand Down
2 changes: 1 addition & 1 deletion contracts/extensions/OrderIdInvalidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ contract OrderIdInvalidator is IPreInteraction {
/// @notice Limit order protocol address.
address private immutable _limitOrderProtocol;
/// @notice Stores corresponding maker orders ids and hashes.
mapping(address => mapping(uint32 => bytes32)) private _ordersIdsHashes;
mapping(address maker => mapping(uint32 orderId => bytes32 orderHash)) private _ordersIdsHashes;

/// @notice Only limit order protocol can call this contract.
modifier onlyLimitOrderProtocol() {
Expand Down
18 changes: 9 additions & 9 deletions contracts/helpers/SeriesEpochManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pragma solidity 0.8.19;
/// @title A helper contract to manage nonce with the series
contract SeriesEpochManager {
error AdvanceEpochFailed();
event EpochIncreased(address indexed maker, uint256 series, uint256 newNonce);
event EpochIncreased(address indexed maker, uint256 series, uint256 newEpoch);

// {
// 1: {
Expand All @@ -18,7 +18,7 @@ contract SeriesEpochManager {
// },
// ...
// }
mapping(uint256 => uint256) private _epochs;
mapping(uint256 seriesId => uint256 epoch) private _epochs;

/// @notice Returns nonce for `maker` and `series`
function epoch(address maker, uint96 series) public view returns(uint256) {
Expand All @@ -35,15 +35,15 @@ contract SeriesEpochManager {
if (amount == 0 || amount > 255) revert AdvanceEpochFailed();
unchecked {
uint256 key = uint160(msg.sender) | (uint256(series) << 160);
uint256 newNonce = _epochs[key] + amount;
_epochs[key] = newNonce;
emit EpochIncreased(msg.sender, series, newNonce);
uint256 newEpoch = _epochs[key] + amount;
_epochs[key] = newEpoch;
emit EpochIncreased(msg.sender, series, newEpoch);
}
}

/// @notice Checks if `maker` has specified `makerNonce` for `series`
/// @return Result True if `maker` has specified nonce. Otherwise, false
function epochEquals(address maker, uint256 series, uint256 makerNonce) public view returns(bool) {
return _epochs[uint160(maker) | (uint256(series) << 160)] == makerNonce;
/// @notice Checks if `maker` has specified `makerEpoch` for `series`
/// @return Result True if `maker` has specified epoch. Otherwise, false
function epochEquals(address maker, uint256 series, uint256 makerEpoch) public view returns(bool) {
return _epochs[uint160(maker) | (uint256(series) << 160)] == makerEpoch;
}
}
2 changes: 1 addition & 1 deletion contracts/helpers/SeriesNonceManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ contract SeriesNonceManager {
// },
// ...
// }
mapping(uint256 => mapping(address => uint256)) public nonce;
mapping(uint256 series => mapping(address maker => uint256 nonce)) public nonce;

/// @notice Advances nonce by one
function increaseNonce(uint8 series) external {
Expand Down
23 changes: 21 additions & 2 deletions contracts/interfaces/IOrderMixin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,32 @@ interface IOrderMixin {
);

/**
* @notice Emitted when order gets filled
* @notice Emitted when order without `useBitInvalidator` gets cancelled
* @param orderHash Hash of the order
*/
event OrderCancelled(
bytes32 orderHash
);

/**
* @notice Emitted when order with `useBitInvalidator` gets cancelled
* @param maker Maker address
* @param slotIndex Slot index that was updated
* @param slotValue New slot value
*/
event BitInvalidatorUpdated(
address indexed maker,
uint256 slotIndex,
uint256 slotValue
);

/**
* @notice Executes a permit and then calls a specified action using delegatecall.
* @param permit The permit data, including the token address, permit parameters and permit signature.
* @param action The action data to be executed using delegatecall.
*/
function permitAndCall(bytes calldata permit, bytes calldata action) external;

/**
* @notice Returns bitmask for double-spend invalidators based on lowest byte of order.info and filled quotes
* @param maker Maker address
Expand All @@ -74,7 +93,7 @@ interface IOrderMixin {
/**
* @notice Returns bitmask for double-spend invalidators based on lowest byte of order.info and filled quotes
* @param orderHash Hash of the order
* @return remainingRaw Remaining amount of the order plus 1 if order was partially filled, otherwise 0
* @return remainingRaw Inverse of the remaining amount of the order if order was filled at least once, otherwise 0
*/
function rawRemainingInvalidatorForOrder(address maker, bytes32 orderHash) external view returns(uint256 remainingRaw);

Expand Down
8 changes: 5 additions & 3 deletions contracts/libraries/BitInvalidatorLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ library BitInvalidatorLib {
error BitInvalidatedOrder();

struct Data {
mapping(uint256 => uint256) _raw;
mapping(uint256 slotIndex => uint256 slotData) _raw;
}

/**
Expand Down Expand Up @@ -51,10 +51,12 @@ library BitInvalidatorLib {
* @param self The data structure.
* @param nonce The nonce identifying the slot.
* @param additionalMask A mask of bits to be invalidated.
* @return result Resulting validity status of entities in the slot as a uint256.
*/
function massInvalidate(Data storage self, uint256 nonce, uint256 additionalMask) internal {
function massInvalidate(Data storage self, uint256 nonce, uint256 additionalMask) internal returns(uint256 result) {
uint256 invalidatorSlot = nonce >> 8;
uint256 invalidatorBits = (1 << (nonce & 0xff)) | additionalMask;
self._raw[invalidatorSlot] |= invalidatorBits;
result = self._raw[invalidatorSlot] | invalidatorBits;
self._raw[invalidatorSlot] = result;
}
}
4 changes: 2 additions & 2 deletions contracts/libraries/ExtensionLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@ library ExtensionLib {
* @dev The first 32 bytes of an extension calldata contain offsets to the end of each field within the calldata.
* @param extension The calldata from which the field is to be retrieved.
* @param field The specific dynamic field to retrieve from the extension.
* @return result A bytes calldata representing the requested field.
* @return calldata Bytes representing the requested field.
*/
function _get(bytes calldata extension, DynamicField field) private pure returns(bytes calldata result) {
function _get(bytes calldata extension, DynamicField field) private pure returns(bytes calldata) {
if (extension.length < 0x20) return msg.data[:0];

Offsets offsets;
Expand Down
4 changes: 2 additions & 2 deletions contracts/libraries/RemainingInvalidatorLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ type RemainingInvalidator is uint256;
* @title RemainingInvalidatorLib
* @notice The library provides a mechanism to invalidate order based on the remaining amount of the order.
* @dev The remaining amount is used as a nonce to invalidate the order.
* When order is created, the remaining invalidator is 0. When the order is filled, the remaining invalidator is type(uint256).max.
* When order is filled partially, the remaining invalidator is the negation of the remaining amount.
* When order is created, the remaining invalidator is 0.
* When order is filled, the remaining invalidator is the inverse of the remaining amount.
*/
library RemainingInvalidatorLib {

Expand Down
2 changes: 1 addition & 1 deletion description.md
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ The limit order protocol offers several helper functions for creating conditions
| calldata | | |
| --- | --- | --- |
| 1-64 bytes | 65-320 bytes | 321-448 bytes |
| calldata (predicate1) | calldata (predicate2) | calldata (predicate2) |
| calldata (predicate1) | calldata (predicate2) | calldata (predicate3) |

| offsets (uint256) | | | |
| --- | --- | --- | --- |
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"rimraf": "5.0.1",
"solc": "0.8.19",
"solhint": "3.4.1",
"solidity-coverage": "0.8.2",
"solidity-coverage": "0.8.5",
"solidity-docgen": "0.5.17",
"zksync-web3": "0.14.3"
},
Expand Down
46 changes: 8 additions & 38 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1190,7 +1190,7 @@
"@sentry/types" "5.30.0"
tslib "^1.9.3"

"@solidity-parser/parser@^0.14.0", "@solidity-parser/parser@^0.14.1":
"@solidity-parser/parser@^0.14.0":
version "0.14.5"
resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804"
integrity sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==
Expand Down Expand Up @@ -4476,37 +4476,7 @@ mnemonist@^0.38.0:
dependencies:
obliterator "^2.0.0"

[email protected]:
version "7.1.2"
resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.1.2.tgz#8e40d198acf91a52ace122cd7599c9ab857b29e6"
integrity sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA==
dependencies:
ansi-colors "3.2.3"
browser-stdout "1.3.1"
chokidar "3.3.0"
debug "3.2.6"
diff "3.5.0"
escape-string-regexp "1.0.5"
find-up "3.0.0"
glob "7.1.3"
growl "1.10.5"
he "1.2.0"
js-yaml "3.13.1"
log-symbols "3.0.0"
minimatch "3.0.4"
mkdirp "0.5.5"
ms "2.1.1"
node-environment-flags "1.0.6"
object.assign "4.1.0"
strip-json-comments "2.0.1"
supports-color "6.0.0"
which "1.3.1"
wide-align "1.1.3"
yargs "13.3.2"
yargs-parser "13.1.2"
yargs-unparser "1.6.0"

mocha@^10.0.0:
[email protected], mocha@^10.0.0:
version "10.2.0"
resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8"
integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==
Expand Down Expand Up @@ -5581,13 +5551,13 @@ [email protected]:
optionalDependencies:
prettier "^2.8.3"

[email protected].2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.2.tgz#bc39604ab7ce0a3fa7767b126b44191830c07813"
integrity sha512-cv2bWb7lOXPE9/SSleDO6czkFiMHgP4NXPj+iW9W7iEKLBk7Cj0AGBiNmGX3V1totl9wjPrT0gHmABZKZt65rQ==
[email protected].5:
version "0.8.5"
resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.5.tgz#64071c3a0c06a0cecf9a7776c35f49edc961e875"
integrity sha512-6C6N6OV2O8FQA0FWA95FdzVH+L16HU94iFgg5wAFZ29UpLFkgNI/DRR2HotG1bC0F4gAc/OMs2BJI44Q/DYlKQ==
dependencies:
"@ethersproject/abi" "^5.0.9"
"@solidity-parser/parser" "^0.14.1"
"@solidity-parser/parser" "^0.16.0"
chalk "^2.4.2"
death "^1.1.0"
detect-port "^1.3.0"
Expand All @@ -5598,7 +5568,7 @@ [email protected]:
globby "^10.0.1"
jsonschema "^1.2.4"
lodash "^4.17.15"
mocha "7.1.2"
mocha "10.2.0"
node-emoji "^1.10.0"
pify "^4.0.1"
recursive-readdir "^2.2.2"
Expand Down

0 comments on commit f3d2033

Please sign in to comment.