Skip to content

Commit

Permalink
Merge pull request #40 from clober-dex/feat/priceBook-deployer
Browse files Browse the repository at this point in the history
Feat/price book deployer
  • Loading branch information
graykode committed Apr 18, 2023
2 parents 9db13ad + 8a4f9b2 commit be7147b
Show file tree
Hide file tree
Showing 17 changed files with 294 additions and 73 deletions.
23 changes: 11 additions & 12 deletions contracts/MarketFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/Create2.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import "./interfaces/CloberMarketFactory.sol";
Expand All @@ -14,6 +13,8 @@ import "./utils/ReentrancyGuard.sol";
import "./OrderNFT.sol";
import "./utils/BoringERC20.sol";
import "./interfaces/CloberMarketDeployer.sol";
import "./interfaces/CloberOrderTokenDeployer.sol";
import "./interfaces/CloberPriceBookDeployer.sol";
import "./markets/GeometricPriceBook.sol";
import "./markets/ArithmeticPriceBook.sol";

Expand All @@ -27,8 +28,9 @@ contract MarketFactory is CloberMarketFactory, ReentrancyGuard, RevertOnDelegate

uint256 private immutable _cachedChainId;
address public immutable override marketDeployer;
address public immutable override priceBookDeployer;
address public immutable override orderTokenDeployer;
address public immutable override canceler;
bytes32 private immutable _orderTokenBytecodeHash;

mapping(bytes32 => address) private _deployedPriceBook;
mapping(address => bool) public override registeredQuoteTokens;
Expand Down Expand Up @@ -59,6 +61,8 @@ contract MarketFactory is CloberMarketFactory, ReentrancyGuard, RevertOnDelegate

constructor(
address marketDeployer_,
address priceBookDeployer_,
address orderTokenDeployer_,
address initialDaoTreasury,
address canceler_,
address[] memory initialQuoteTokenRegistrations_
Expand All @@ -68,11 +72,10 @@ contract MarketFactory is CloberMarketFactory, ReentrancyGuard, RevertOnDelegate
emit ChangeOwner(address(0), msg.sender);

marketDeployer = marketDeployer_;
priceBookDeployer = priceBookDeployer_;
orderTokenDeployer = orderTokenDeployer_;
daoTreasury = initialDaoTreasury;
emit ChangeDaoTreasury(address(0), initialDaoTreasury);
_orderTokenBytecodeHash = keccak256(
abi.encodePacked(type(OrderNFT).creationCode, abi.encode(address(this), canceler_))
);
canceler = canceler_;

for (uint256 i = 0; i < initialQuoteTokenRegistrations_.length; ++i) {
Expand Down Expand Up @@ -101,7 +104,7 @@ contract MarketFactory is CloberMarketFactory, ReentrancyGuard, RevertOnDelegate
bytes32 priceBookKey = _priceBookKey(a, r, MarketType.VOLATILE);
priceBook = _deployedPriceBook[priceBookKey];
if (priceBook == address(0)) {
priceBook = address(new GeometricPriceBook(a, r));
priceBook = CloberPriceBookDeployer(priceBookDeployer).deployGeometricPriceBook(a, r);
_deployedPriceBook[priceBookKey] = priceBook;
}
}
Expand Down Expand Up @@ -153,7 +156,7 @@ contract MarketFactory is CloberMarketFactory, ReentrancyGuard, RevertOnDelegate
bytes32 priceBookKey = _priceBookKey(a, d, MarketType.STABLE);
priceBook = _deployedPriceBook[priceBookKey];
if (priceBook == address(0)) {
priceBook = address(new ArithmeticPriceBook(a, d));
priceBook = CloberPriceBookDeployer(priceBookDeployer).deployArithmeticPriceBook(a, d);
_deployedPriceBook[priceBookKey] = priceBook;
}
}
Expand Down Expand Up @@ -257,7 +260,7 @@ contract MarketFactory is CloberMarketFactory, ReentrancyGuard, RevertOnDelegate
}

function _deployToken(bytes32 salt) internal returns (address) {
return address(new OrderNFT{salt: salt}(address(this), canceler));
return CloberOrderTokenDeployer(orderTokenDeployer).deploy(salt);
}

function _initToken(
Expand Down Expand Up @@ -294,10 +297,6 @@ contract MarketFactory is CloberMarketFactory, ReentrancyGuard, RevertOnDelegate
emit ChangeHost(market, address(0), host);
}

function computeTokenAddress(uint256 marketNonce) external view returns (address) {
return Create2.computeAddress(_calculateSalt(marketNonce), _orderTokenBytecodeHash);
}

function getMarketInfo(address market) external view returns (MarketInfo memory) {
return _marketInfos[market];
}
Expand Down
18 changes: 12 additions & 6 deletions contracts/interfaces/CloberMarketFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,18 @@ interface CloberMarketFactory {
*/
function marketDeployer() external view returns (address);

/**
* @notice Returns the address of the priceBookDeployer.
* @return The address of the priceBookDeployer.
*/
function priceBookDeployer() external view returns (address);

/**
* @notice Returns the address of the orderTokenDeployer.
* @return The address of the orderTokenDeployer.
*/
function orderTokenDeployer() external view returns (address);

/**
* @notice Returns the address of the OrderCanceler.
* @return The address of the OrderCanceler.
Expand Down Expand Up @@ -236,12 +248,6 @@ interface CloberMarketFactory {
*/
function executeHandOverHost(address market) external;

/**
* @notice Computes the OrderNFT contract address.
* @param marketNonce The nonce to compute the OrderNFT contract address via CREATE2.
*/
function computeTokenAddress(uint256 marketNonce) external view returns (address);

enum MarketType {
NONE,
VOLATILE,
Expand Down
14 changes: 14 additions & 0 deletions contracts/interfaces/CloberOrderTokenDeployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.0;

interface CloberOrderTokenDeployer {
// TODO: add docstring
function deploy(bytes32 salt) external returns (address);

/**
* @notice Computes the OrderNFT contract address.
* @param salt The salt to compute the OrderNFT contract address via CREATE2.
*/
function computeTokenAddress(bytes32 salt) external view returns (address);
}
11 changes: 11 additions & 0 deletions contracts/interfaces/CloberPriceBookDeployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.0;

interface CloberPriceBookDeployer {
// TODO: add docstring
function deployArithmeticPriceBook(uint128 a, uint128 d) external returns (address);

// TODO: add docstring
function deployGeometricPriceBook(uint128 a, uint128 r) external returns (address);
}
34 changes: 34 additions & 0 deletions contracts/markets/OrderTokenDeployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: -
// License: https://license.clober.io/LICENSE.pdf

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/Create2.sol";

import "../interfaces/CloberOrderTokenDeployer.sol";
import "../OrderNFT.sol";

contract OrderTokenDeployer is CloberOrderTokenDeployer {
address private immutable _factory;
address private immutable _canceler;
bytes32 private immutable _orderTokenBytecodeHash;

constructor(address factory_, address canceler_) {
_factory = factory_;
_canceler = canceler_;
_orderTokenBytecodeHash = keccak256(
abi.encodePacked(type(OrderNFT).creationCode, abi.encode(factory_, canceler_))
);
}

function deploy(bytes32 salt) external returns (address) {
if (msg.sender != _factory) {
revert Errors.CloberError(Errors.ACCESS);
}
return address(new OrderNFT{salt: salt}(_factory, _canceler));
}

function computeTokenAddress(bytes32 salt) external view returns (address) {
return Create2.computeAddress(salt, _orderTokenBytecodeHash);
}
}
52 changes: 52 additions & 0 deletions contracts/markets/PriceDeployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: -
// License: https://license.clober.io/LICENSE.pdf

pragma solidity ^0.8.0;

import "./ArithmeticPriceBook.sol";
import "./GeometricPriceBook.sol";
import "../interfaces/CloberPriceBookDeployer.sol";

import "@openzeppelin/contracts/utils/Create2.sol";

contract PriceBookDeployer is CloberPriceBookDeployer {
address private immutable _factory;

constructor(address factory_) {
_factory = factory_;
}

function deployArithmeticPriceBook(uint128 a, uint128 d) external returns (address priceBook) {
if (msg.sender != _factory) {
revert Errors.CloberError(Errors.ACCESS);
}
bytes32 salt = keccak256(abi.encodePacked(a, d));
priceBook = address(new ArithmeticPriceBook{salt: salt}(a, d));
}

function deployGeometricPriceBook(uint128 a, uint128 r) external returns (address priceBook) {
if (msg.sender != _factory) {
revert Errors.CloberError(Errors.ACCESS);
}
bytes32 salt = keccak256(abi.encodePacked(a, r));
priceBook = address(new GeometricPriceBook{salt: salt}(a, r));
}

function computeArithmeticPriceBookAddress(uint128 a, uint128 d) external view returns (address) {
bytes32 salt = keccak256(abi.encodePacked(a, d));
return
Create2.computeAddress(
salt,
keccak256(abi.encodePacked(type(ArithmeticPriceBook).creationCode, abi.encode(a, d)))
);
}

function computeGeometricPriceBookAddress(uint128 a, uint128 r) external view returns (address) {
bytes32 salt = keccak256(abi.encodePacked(a, r));
return
Create2.computeAddress(
salt,
keccak256(abi.encodePacked(type(GeometricPriceBook).creationCode, abi.encode(a, r)))
);
}
}
7 changes: 7 additions & 0 deletions deployments/1442/address.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"OrderCanceler": "0x03A2D3e0e4b073CDE7E227098B4257844910F094",
"MarketDeployer": "0x6baa80Fff765eB9994b65AfFA121517910316074",
"PriceBookDeployer": "0x30A075a4244a5A02e64a95eD3289234926baf02f",
"MarketFactory": "0x7CE81Be8B48311D2E9e89fE4731B58D2CC8Aa1E4",
"MarketRouter": "0x0ccc1fd632a5beE5bD9eda3aad490119eE50648F"
}
36 changes: 28 additions & 8 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import {
localhost,
mainnet,
polygon,
polygonZkEvm,
polygonZkEvmTestnet,
} from '@wagmi/chains'

const SKIP_LOAD = process.env.SKIP_LOAD === 'true'
Expand Down Expand Up @@ -68,7 +70,12 @@ const getMainnetPrivateKey = () => {
}
}

const prodNetworks = new Set<number>([mainnet.id, polygon.id, arbitrum.id])
const prodNetworks = new Set<number>([
mainnet.id,
polygon.id,
arbitrum.id,
polygonZkEvm.id,
])
if (network && prodNetworks.has(network)) {
if (privateKey) {
return privateKey
Expand Down Expand Up @@ -161,6 +168,20 @@ const config: HardhatConfig = {
tags: ['mainnet', 'prod'],
companionNetworks: {},
},
[polygonZkEvm.id]: {
url: polygonZkEvm.rpcUrls.default.http[0],
chainId: polygonZkEvm.id,
accounts: [getMainnetPrivateKey()],
gas: 'auto',
gasPrice: 'auto',
gasMultiplier: 1,
timeout: 3000000,
httpHeaders: {},
live: true,
saveDeployments: true,
tags: ['mainnet', 'prod'],
companionNetworks: {},
},
[arbitrumGoerli.id]: {
url: arbitrumGoerli.rpcUrls.default.http[0],
chainId: arbitrumGoerli.id,
Expand All @@ -178,17 +199,16 @@ const config: HardhatConfig = {
tags: ['testnet', 'dev'],
companionNetworks: {},
},
// TODO: use `@wagmi/chains`
[1442]: {
url: 'https://rpc.public.zkevm-test.net',
chainId: 1442,
[polygonZkEvmTestnet.id]: {
url: polygonZkEvmTestnet.rpcUrls.default.http[0],
chainId: polygonZkEvmTestnet.id,
accounts:
process.env.DEV_PRIVATE_KEY !== undefined
? [process.env.DEV_PRIVATE_KEY]
: [],
gas: 7800000,
gasPrice: 3500000000,
gasMultiplier: 1,
gas: 10000000,
gasPrice: 100000000000,
gasMultiplier: 1.5,
timeout: 3000000,
httpHeaders: {},
live: true,
Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
"dependencies": {
"@clober/library": "^1.0.0",
"@openzeppelin/contracts": "4.7.3",
"@wagmi/chains": "^0.2.8",
"@wagmi/chains": "^0.2.17",
"solidity-docgen": "^0.6.0-beta.32"
}
}
11 changes: 10 additions & 1 deletion task/dev-deploy/01_market_factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,27 @@ deployerTask(
const nonce = await signer.getTransactionCount('latest')
const computedFactoryAddress = computeCreate1Address(
signer.address,
BigNumber.from(nonce + 1),
BigNumber.from(nonce + 3),
)

const marketDeployer = await deployer.deploy('MarketDeployer', [
computedFactoryAddress,
])
const priceBookDeployer = await deployer.deploy('PriceBookDeployer', [
computedFactoryAddress,
])
const orderTokenDeployer = await deployer.deploy('OrderTokenDeployer', [
computedFactoryAddress,
canceler,
])

const initialQuoteTokenRegistrations = [
...new Set(marketConfigs[hre.network.name]?.map((v) => v.quoteToken)),
]
const factory = await deployer.deploy('MarketFactory', [
marketDeployer,
priceBookDeployer,
orderTokenDeployer,
signer.address,
canceler,
initialQuoteTokenRegistrations,
Expand Down

0 comments on commit be7147b

Please sign in to comment.