Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 2 additions & 40 deletions contracts/extensions/NativeOrderFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,19 @@

pragma solidity 0.8.30;

import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol";

Check warning on line 5 in contracts/extensions/NativeOrderFactory.sol

View workflow job for this annotation

GitHub Actions / lint

imported name Clones is not used
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Address, AddressLib } from "@1inch/solidity-utils/contracts/libraries/AddressLib.sol";

Check warning on line 7 in contracts/extensions/NativeOrderFactory.sol

View workflow job for this annotation

GitHub Actions / lint

imported name AddressLib is not used

Check warning on line 7 in contracts/extensions/NativeOrderFactory.sol

View workflow job for this annotation

GitHub Actions / lint

imported name Address is not used
import { SafeERC20, IERC20, IWETH } from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol";

Check warning on line 8 in contracts/extensions/NativeOrderFactory.sol

View workflow job for this annotation

GitHub Actions / lint

imported name SafeERC20 is not used

import { IOrderMixin } from "../interfaces/IOrderMixin.sol";

Check warning on line 10 in contracts/extensions/NativeOrderFactory.sol

View workflow job for this annotation

GitHub Actions / lint

imported name IOrderMixin is not used
import { Errors } from "../libraries/Errors.sol";

Check warning on line 11 in contracts/extensions/NativeOrderFactory.sol

View workflow job for this annotation

GitHub Actions / lint

imported name Errors is not used
import { EIP712Alien } from "../utils/EIP712Alien.sol";
import { OrderLib } from "../OrderLib.sol";

Check warning on line 13 in contracts/extensions/NativeOrderFactory.sol

View workflow job for this annotation

GitHub Actions / lint

imported name OrderLib is not used
import { NativeOrderImpl } from "./NativeOrderImpl.sol";
import { NativeOrderFactoryBase } from "./NativeOrderFactoryBase.sol";

contract NativeOrderFactory is Ownable, EIP712Alien {
using Clones for address;
using AddressLib for Address;
using SafeERC20 for IERC20;
using OrderLib for IOrderMixin.Order;

event NativeOrderCreated(address maker, bytes32 orderHash, address clone, uint256 value);

error OrderReceiverShouldBeSetCorrectly(address receiver);
error OrderMakerShouldBeMsgSender(address expected, address actual);
error OrderMakingAmountShouldBeEqualToMsgValue(uint256 expected, uint256 actual);

address public immutable IMPLEMENTATION;

contract NativeOrderFactory is NativeOrderFactoryBase {
constructor(
IWETH weth,
address limitOrderProtocol,
Expand All @@ -48,30 +36,4 @@
version
));
}

function create(IOrderMixin.Order calldata makerOrder) external payable returns (address clone) {
// Validate main order parameters
if (makerOrder.maker.get() != msg.sender) revert OrderMakerShouldBeMsgSender(msg.sender, makerOrder.maker.get());
address receiver = makerOrder.receiver.get();
if (receiver == address(0) || receiver == address(this)) revert OrderReceiverShouldBeSetCorrectly(receiver);
if (msg.value != makerOrder.makingAmount) revert OrderMakingAmountShouldBeEqualToMsgValue(makerOrder.makingAmount, msg.value);

bytes32 makerOrderHash = makerOrder.hash(_domainSeparatorV4());
clone = IMPLEMENTATION.cloneDeterministic(makerOrderHash);
NativeOrderImpl(payable(clone)).depositAndApprove{ value: msg.value }();

IOrderMixin.Order memory order = makerOrder;
order.maker = Address.wrap(uint160(clone));
bytes32 orderHash = order.hashMemory(_domainSeparatorV4());
emit NativeOrderCreated(msg.sender, orderHash, clone, msg.value);
}

function rescueFunds(address token, address to, uint256 amount) external onlyOwner {
if (token == address(0)) {
(bool success, ) = payable(to).call{ value: amount }("");
if (!success) revert Errors.ETHTransferFailed();
} else {
IERC20(token).safeTransfer(to, amount);
}
}
}
59 changes: 59 additions & 0 deletions contracts/extensions/NativeOrderFactoryBase.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.30;

import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Address, AddressLib } from "@1inch/solidity-utils/contracts/libraries/AddressLib.sol";
import { SafeERC20, IERC20, IWETH } from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol";

Check warning on line 8 in contracts/extensions/NativeOrderFactoryBase.sol

View workflow job for this annotation

GitHub Actions / lint

imported name IWETH is not used

import { IOrderMixin } from "../interfaces/IOrderMixin.sol";
import { Errors } from "../libraries/Errors.sol";
import { EIP712Alien } from "../utils/EIP712Alien.sol";
import { OrderLib } from "../OrderLib.sol";
import { NativeOrderImpl } from "./NativeOrderImpl.sol";

abstract contract NativeOrderFactoryBase is Ownable, EIP712Alien {
using Clones for address;
using AddressLib for Address;
using SafeERC20 for IERC20;
using OrderLib for IOrderMixin.Order;

event NativeOrderCreated(address maker, bytes32 orderHash, address clone, uint256 value);

error OrderReceiverShouldBeSetCorrectly(address receiver);
error OrderMakerShouldBeMsgSender(address expected, address actual);
error OrderMakingAmountShouldBeEqualToMsgValue(uint256 expected, uint256 actual);

address public immutable IMPLEMENTATION;

function create(IOrderMixin.Order calldata makerOrder) external payable returns (address clone) {
// Validate main order parameters
if (makerOrder.maker.get() != msg.sender) revert OrderMakerShouldBeMsgSender(msg.sender, makerOrder.maker.get());
address receiver = makerOrder.receiver.get();
if (receiver == address(0) || receiver == address(this)) revert OrderReceiverShouldBeSetCorrectly(receiver);
if (msg.value != makerOrder.makingAmount) revert OrderMakingAmountShouldBeEqualToMsgValue(makerOrder.makingAmount, msg.value);

bytes32 makerOrderHash = makerOrder.hash(_domainSeparatorV4());
clone = _deployNativeOrder(IMPLEMENTATION, makerOrderHash);
NativeOrderImpl(payable(clone)).depositAndApprove{ value: msg.value }();

IOrderMixin.Order memory order = makerOrder;
order.maker = Address.wrap(uint160(clone));
bytes32 orderHash = order.hashMemory(_domainSeparatorV4());
emit NativeOrderCreated(msg.sender, orderHash, clone, msg.value);
}

function rescueFunds(address token, address to, uint256 amount) external onlyOwner {
if (token == address(0)) {
(bool success, ) = payable(to).call{ value: amount }("");
if (!success) revert Errors.ETHTransferFailed();
} else {
IERC20(token).safeTransfer(to, amount);
}
}

function _deployNativeOrder(address implementation, bytes32 salt) internal virtual returns (address) {
return implementation.cloneDeterministic(salt);
}
}
4 changes: 2 additions & 2 deletions contracts/extensions/NativeOrderImpl.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ contract NativeOrderImpl is IERC1271, EIP712Alien, OnlyWethReceiver {
IWETH private immutable _WETH;
address private immutable _LOP;
address private immutable _IMPLEMENTATION = address(this);
address private immutable _FACTORY;
address internal immutable _FACTORY;
IERC20 private immutable _ACCESS_TOKEN;
uint256 private immutable _CANCELLATION_DELAY;

Expand Down Expand Up @@ -167,7 +167,7 @@ contract NativeOrderImpl is IERC1271, EIP712Alien, OnlyWethReceiver {
return order.hashMemory(_domainSeparatorV4());
}

function _calcCloneAddress(IOrderMixin.Order calldata makerOrder) private view returns(address) {
function _calcCloneAddress(IOrderMixin.Order calldata makerOrder) internal virtual view returns(address) {
bytes32 makerOrderHash = makerOrder.hash(_domainSeparatorV4());
return _IMPLEMENTATION.predictDeterministicAddress(makerOrderHash, _FACTORY);
}
Expand Down
29 changes: 29 additions & 0 deletions contracts/extensions/ZkSync/MinimalProxyZkSync.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.30;

/// @custom:security-contact [email protected]
contract MinimalProxyZkSync {
address private immutable _IMPLEMENTATION;

constructor(address implementation) payable {
_IMPLEMENTATION = implementation;
}

// solhint-disable-next-line no-complex-fallback
fallback() external payable {
address _impl = _IMPLEMENTATION;
assembly ("memory-safe") {

Check warning on line 16 in contracts/extensions/ZkSync/MinimalProxyZkSync.sol

View workflow job for this annotation

GitHub Actions / lint

Avoid to use inline assembly. It is acceptable only in rare cases
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), _impl, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
}
66 changes: 66 additions & 0 deletions contracts/extensions/ZkSync/NativeOrderFactoryZkSync.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.30;

import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Address, AddressLib } from "@1inch/solidity-utils/contracts/libraries/AddressLib.sol";
import { SafeERC20, IERC20, IWETH } from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol";

import { IOrderMixin } from "../../interfaces/IOrderMixin.sol";
import { Errors } from "../../libraries/Errors.sol";

Check warning on line 11 in contracts/extensions/ZkSync/NativeOrderFactoryZkSync.sol

View workflow job for this annotation

GitHub Actions / lint

imported name Errors is not used
import { EIP712Alien } from "../../utils/EIP712Alien.sol";
import { OrderLib } from "../../OrderLib.sol";
import { NativeOrderImplZkSync } from "./NativeOrderImplZkSync.sol";
import { MinimalProxyZkSync } from "./MinimalProxyZkSync.sol";
import { ZkSyncLib } from "./ZkSyncLib.sol";
import { NativeOrderFactoryBase } from "../NativeOrderFactoryBase.sol";

contract NativeOrderFactoryZkSync is NativeOrderFactoryBase {
using Clones for address;
using AddressLib for Address;
using SafeERC20 for IERC20;
using OrderLib for IOrderMixin.Order;

bytes32 public immutable IMPLEMENTATION_INPUT_HASH;
bytes32 private immutable _PROXY_IMPL_BYTECODE_HASH;

constructor(
IWETH weth,
address limitOrderProtocol,
IERC20 accessToken,
uint256 cancellationDelay, // Recommended 60 seconds delay after order expiration for rewardable cancellation
string memory name,
string memory version
)
Ownable(msg.sender)
EIP712Alien(limitOrderProtocol, name, version)
{
IMPLEMENTATION = address(new NativeOrderImplZkSync(
weth,
address(this),
limitOrderProtocol,
accessToken,
cancellationDelay,
name,
version
));
IMPLEMENTATION_INPUT_HASH = keccak256(abi.encode(IMPLEMENTATION));

MinimalProxyZkSync proxyImpl = new MinimalProxyZkSync(IMPLEMENTATION);
bytes32 bytecodeHash;
assembly ("memory-safe") {
bytecodeHash := extcodehash(proxyImpl)
}
_PROXY_IMPL_BYTECODE_HASH = bytecodeHash;
}

function addressOfNativeOrder(IOrderMixin.Order calldata makerOrder) external view returns (address) {
bytes32 makerOrderHash = makerOrder.hash(_domainSeparatorV4());
return ZkSyncLib.computeAddressZkSync(makerOrderHash, _PROXY_IMPL_BYTECODE_HASH, address(this), IMPLEMENTATION_INPUT_HASH);
}

function _deployNativeOrder(address implementation, bytes32 salt) internal override virtual returns (address) {
return address(new MinimalProxyZkSync{salt: salt}(implementation));
}
}
46 changes: 46 additions & 0 deletions contracts/extensions/ZkSync/NativeOrderImplZkSync.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.30;

import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol";
import { IERC1271 } from "@openzeppelin/contracts/interfaces/IERC1271.sol";
import { Address, AddressLib } from "@1inch/solidity-utils/contracts/libraries/AddressLib.sol";
import { SafeERC20, IERC20, IWETH } from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol";
import { OnlyWethReceiver } from "@1inch/solidity-utils/contracts/mixins/OnlyWethReceiver.sol";

import { MakerTraits, MakerTraitsLib } from "../../libraries/MakerTraitsLib.sol";
import { OrderLib, IOrderMixin } from "../../OrderLib.sol";
import { NativeOrderImpl } from "../NativeOrderImpl.sol";
import { ZkSyncLib } from "./ZkSyncLib.sol";

contract NativeOrderImplZkSync is NativeOrderImpl {
using MakerTraitsLib for MakerTraits;
using OrderLib for IOrderMixin.Order;

bytes32 private immutable _INPUT_HASH;

constructor(
IWETH weth,
address nativeOrderFactory,
address limitOrderProtocol,
IERC20 accessToken,
uint256 cancellationDelay, // Recommended 60 seconds delay after order expiration for rewardable cancellation
string memory name,
string memory version
)
NativeOrderImpl(weth, nativeOrderFactory, limitOrderProtocol, accessToken, cancellationDelay, name, version)
{
_INPUT_HASH = keccak256(abi.encode(address(this)));
}

function _calcCloneAddress(IOrderMixin.Order calldata makerOrder) internal override view returns(address) {
bytes32 makerOrderHash = makerOrder.hash(_domainSeparatorV4());
bytes32 bytecodeHash;
assembly ("memory-safe") {
bytecodeHash := extcodehash(address())
}
// return _IMPLEMENTATION.predictDeterministicAddress(makerOrderHash, _FACTORY);
return ZkSyncLib.computeAddressZkSync(makerOrderHash, bytecodeHash, _FACTORY, _INPUT_HASH);
}
}
37 changes: 37 additions & 0 deletions contracts/extensions/ZkSync/ZkSyncLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

/**
* @title Library for ZkSync contracts.
* @custom:security-contact [email protected]
*/
library ZkSyncLib {
// keccak256("zksyncCreate2")
bytes32 constant private _CREATE2_PREFIX = 0x2020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca494;

/**
* @notice Returns the address of the contract deployed with CREATE2.
* @param salt The salt used for the deployment.
* @param bytecodeHash The hash of the bytecode.
* @param deployer The address of the deployer.
* @param inputHash The hash of the input.
* @return addr The computed address.
*/
function computeAddressZkSync(
bytes32 salt,
bytes32 bytecodeHash,
address deployer,
bytes32 inputHash
) internal pure returns (address addr) {
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(ptr, _CREATE2_PREFIX)
mstore(add(ptr, 0x20), deployer)
mstore(add(ptr, 0x40), salt)
mstore(add(ptr, 0x60), bytecodeHash)
mstore(add(ptr, 0x80), inputHash)
addr := and(keccak256(ptr, 0xa0), 0xffffffffffffffffffffffffffffffffffffffff)
}
}
}
Loading