/
AlgebraFactory.sol
188 lines (152 loc) · 7.46 KB
/
AlgebraFactory.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.20;
import './libraries/Constants.sol';
import './interfaces/IAlgebraFactory.sol';
import './interfaces/IAlgebraPoolDeployer.sol';
import './interfaces/vault/IAlgebraVaultFactory.sol';
import './interfaces/plugin/IAlgebraPluginFactory.sol';
import './AlgebraCommunityVault.sol';
import '@openzeppelin/contracts/access/Ownable2Step.sol';
import '@openzeppelin/contracts/access/AccessControlEnumerable.sol';
/// @title Algebra factory
/// @notice Is used to deploy pools and its plugins
/// @dev Version: Algebra Integral 1.0
contract AlgebraFactory is IAlgebraFactory, Ownable2Step, AccessControlEnumerable {
/// @inheritdoc IAlgebraFactory
bytes32 public constant override POOLS_ADMINISTRATOR_ROLE = keccak256('POOLS_ADMINISTRATOR'); // it`s here for the public visibility of the value
/// @inheritdoc IAlgebraFactory
address public immutable override poolDeployer;
/// @inheritdoc IAlgebraFactory
uint16 public override defaultCommunityFee;
/// @inheritdoc IAlgebraFactory
uint16 public override defaultFee;
/// @inheritdoc IAlgebraFactory
int24 public override defaultTickspacing;
/// @inheritdoc IAlgebraFactory
uint256 public override renounceOwnershipStartTimestamp;
/// @dev time delay before ownership renouncement can be finished
uint256 private constant RENOUNCE_OWNERSHIP_DELAY = 1 days;
/// @inheritdoc IAlgebraFactory
IAlgebraPluginFactory public defaultPluginFactory;
/// @inheritdoc IAlgebraFactory
IAlgebraVaultFactory public vaultFactory;
/// @inheritdoc IAlgebraFactory
mapping(address => mapping(address => address)) public override poolByPair;
/// @inheritdoc IAlgebraFactory
/// @dev keccak256 of AlgebraPool init bytecode. Used to compute pool address deterministically
bytes32 public constant POOL_INIT_CODE_HASH = 0xf96d2474815c32e070cd63233f06af5413efc5dcb430aee4ff18cc29007c562d;
constructor(address _poolDeployer) {
require(_poolDeployer != address(0));
poolDeployer = _poolDeployer;
defaultTickspacing = Constants.INIT_DEFAULT_TICK_SPACING;
defaultFee = Constants.INIT_DEFAULT_FEE;
emit DefaultTickspacing(Constants.INIT_DEFAULT_TICK_SPACING);
emit DefaultFee(Constants.INIT_DEFAULT_FEE);
}
/// @inheritdoc IAlgebraFactory
function owner() public view override(IAlgebraFactory, Ownable) returns (address) {
return super.owner();
}
/// @inheritdoc IAlgebraFactory
function hasRoleOrOwner(bytes32 role, address account) public view override returns (bool) {
return (owner() == account || super.hasRole(role, account));
}
/// @inheritdoc IAlgebraFactory
function defaultConfigurationForPool(
address pool
) external view override returns (uint16 communityFee, int24 tickSpacing, uint16 fee, address communityVault) {
if (address(vaultFactory) != address(0)) {
communityVault = vaultFactory.getVaultForPool(pool);
}
return (defaultCommunityFee, defaultTickspacing, defaultFee, communityVault);
}
/// @inheritdoc IAlgebraFactory
function computePoolAddress(address token0, address token1) public view override returns (address pool) {
pool = address(uint160(uint256(keccak256(abi.encodePacked(hex'ff', poolDeployer, keccak256(abi.encode(token0, token1)), POOL_INIT_CODE_HASH)))));
}
/// @inheritdoc IAlgebraFactory
function createPool(address tokenA, address tokenB) external override returns (address pool) {
require(tokenA != tokenB);
(address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0));
require(poolByPair[token0][token1] == address(0));
address defaultPlugin;
if (address(defaultPluginFactory) != address(0)) {
defaultPlugin = defaultPluginFactory.createPlugin(computePoolAddress(token0, token1), token0, token1);
}
pool = IAlgebraPoolDeployer(poolDeployer).deploy(defaultPlugin, token0, token1);
poolByPair[token0][token1] = pool; // to avoid future addresses comparison we are populating the mapping twice
poolByPair[token1][token0] = pool;
emit Pool(token0, token1, pool);
if (address(vaultFactory) != address(0)) {
vaultFactory.createVaultForPool(pool);
}
}
/// @inheritdoc IAlgebraFactory
function setDefaultCommunityFee(uint16 newDefaultCommunityFee) external override onlyOwner {
require(newDefaultCommunityFee <= Constants.MAX_COMMUNITY_FEE);
require(defaultCommunityFee != newDefaultCommunityFee);
if (newDefaultCommunityFee != 0) require(address(vaultFactory) != address(0));
defaultCommunityFee = newDefaultCommunityFee;
emit DefaultCommunityFee(newDefaultCommunityFee);
}
/// @inheritdoc IAlgebraFactory
function setDefaultFee(uint16 newDefaultFee) external override onlyOwner {
require(newDefaultFee <= Constants.MAX_DEFAULT_FEE);
require(defaultFee != newDefaultFee);
defaultFee = newDefaultFee;
emit DefaultFee(newDefaultFee);
}
/// @inheritdoc IAlgebraFactory
function setDefaultTickspacing(int24 newDefaultTickspacing) external override onlyOwner {
require(newDefaultTickspacing >= Constants.MIN_TICK_SPACING);
require(newDefaultTickspacing <= Constants.MAX_TICK_SPACING);
require(newDefaultTickspacing != defaultTickspacing);
defaultTickspacing = newDefaultTickspacing;
emit DefaultTickspacing(newDefaultTickspacing);
}
/// @inheritdoc IAlgebraFactory
function setDefaultPluginFactory(address newDefaultPluginFactory) external override onlyOwner {
require(newDefaultPluginFactory != address(defaultPluginFactory));
defaultPluginFactory = IAlgebraPluginFactory(newDefaultPluginFactory);
emit DefaultPluginFactory(newDefaultPluginFactory);
}
/// @inheritdoc IAlgebraFactory
function setVaultFactory(address newVaultFactory) external override onlyOwner {
require(newVaultFactory != address(vaultFactory));
if (newVaultFactory == address(0)) require(defaultCommunityFee == 0);
vaultFactory = IAlgebraVaultFactory(newVaultFactory);
emit VaultFactory(newVaultFactory);
}
/// @inheritdoc IAlgebraFactory
function startRenounceOwnership() external override onlyOwner {
require(renounceOwnershipStartTimestamp == 0);
renounceOwnershipStartTimestamp = block.timestamp;
emit RenounceOwnershipStart(renounceOwnershipStartTimestamp, renounceOwnershipStartTimestamp + RENOUNCE_OWNERSHIP_DELAY);
}
/// @inheritdoc IAlgebraFactory
function stopRenounceOwnership() external override onlyOwner {
require(renounceOwnershipStartTimestamp != 0);
renounceOwnershipStartTimestamp = 0;
emit RenounceOwnershipStop(block.timestamp);
}
/// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore.
/// Can only be called by the current owner if RENOUNCE_OWNERSHIP_DELAY seconds
/// have passed since the call to the startRenounceOwnership() function.
function renounceOwnership() public override onlyOwner {
require(renounceOwnershipStartTimestamp != 0);
require(block.timestamp - renounceOwnershipStartTimestamp >= RENOUNCE_OWNERSHIP_DELAY);
renounceOwnershipStartTimestamp = 0;
super.renounceOwnership();
emit RenounceOwnershipFinish(block.timestamp);
}
/// @dev Transfers ownership of the contract to a new account (`newOwner`).
/// Modified to fit with the role mechanism.
function _transferOwnership(address newOwner) internal override {
_revokeRole(DEFAULT_ADMIN_ROLE, owner());
super._transferOwnership(newOwner);
if (owner() != address(0)) {
_grantRole(DEFAULT_ADMIN_ROLE, owner());
}
}
}