@zoralabs/coins 0.9.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +179 -114
- package/CHANGELOG.md +46 -0
- package/abis/BaseCoin.json +26 -118
- package/abis/BaseTest.json +47 -0
- package/abis/BuySupplyWithSwapRouterHook.json +40 -0
- package/abis/Coin.json +171 -63
- package/abis/CoinDopplerMultiCurve.json +38 -0
- package/abis/CoinRewardsV4.json +54 -0
- package/abis/CoinTest.json +53 -20
- package/abis/CoinUniV4Test.json +1091 -0
- package/abis/CoinV4.json +234 -211
- package/abis/DeployScript.json +47 -0
- package/abis/DeployedCoinVersionLookup.json +21 -0
- package/abis/DeployedCoinVersionLookupTest.json +716 -0
- package/abis/DifferentNamespaceVersionLookup.json +39 -0
- package/abis/DopplerUniswapV3Test.json +49 -93
- package/abis/ERC20.json +310 -0
- package/abis/FactoryTest.json +85 -7
- package/abis/FeeEstimatorHook.json +1515 -0
- package/abis/HooksDeployment.json +23 -0
- package/abis/HooksTest.json +60 -0
- package/abis/ICoin.json +40 -71
- package/abis/ICoinV3.json +879 -0
- package/abis/ICoinV4.json +915 -0
- package/abis/IDeployedCoinVersionLookup.json +21 -0
- package/abis/IERC721.json +36 -36
- package/abis/IHasPoolKey.json +42 -0
- package/abis/IHasRewardsRecipients.json +54 -0
- package/abis/IHasSwapPath.json +60 -0
- package/abis/IMsgSender.json +15 -0
- package/abis/IPoolConfigEncoding.json +46 -0
- package/abis/ISwapPathRouter.json +92 -0
- package/abis/IUniversalRouter.json +61 -0
- package/abis/IUnlockCallback.json +21 -0
- package/abis/IV4Quoter.json +310 -0
- package/abis/IZoraFactory.json +210 -11
- package/abis/IZoraV4CoinHook.json +348 -4
- package/abis/MockERC20.json +21 -0
- package/abis/MultiOwnableTest.json +47 -0
- package/abis/{CoinConfigurationVersions.json → Position.json} +1 -1
- package/abis/PrintUpgradeCommand.json +9 -0
- package/abis/ProxyShim.json +24 -0
- package/abis/StateLibrary.json +80 -0
- package/abis/TestDeployedCoinVersionLookupImplementation.json +39 -0
- package/abis/TestV4Swap.json +9 -0
- package/abis/UpgradeCoinImpl.json +47 -0
- package/abis/UpgradesTest.json +81 -0
- package/abis/Vm.json +1482 -111
- package/abis/VmSafe.json +856 -32
- package/abis/ZoraFactoryImpl.json +339 -1
- package/abis/ZoraV4CoinHook.json +442 -5
- package/addresses/8453.json +7 -4
- package/addresses/84532.json +8 -5
- package/addresses/dev/8453.json +10 -0
- package/dist/index.cjs +1932 -167
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1928 -167
- package/dist/index.js.map +1 -1
- package/dist/wagmiGenerated.d.ts +2606 -160
- package/dist/wagmiGenerated.d.ts.map +1 -1
- package/foundry.toml +1 -0
- package/package/wagmiGenerated.ts +1941 -164
- package/package.json +8 -3
- package/remappings.txt +6 -1
- package/script/Deploy.s.sol +1 -1
- package/script/DeployDevFactory.s.sol +21 -0
- package/script/DeployHooks.s.sol +1 -1
- package/script/PrintUpgradeCommand.s.sol +13 -0
- package/script/Simulate.s.sol +1 -10
- package/script/TestBackingCoinSwap.s.sol +147 -0
- package/script/TestV4Swap.s.sol +136 -0
- package/script/UpgradeCoinImpl.sol +2 -2
- package/script/UpgradeFactoryImpl.s.sol +2 -2
- package/src/BaseCoin.sol +190 -0
- package/src/Coin.sol +87 -202
- package/src/CoinV4.sol +121 -0
- package/src/ZoraFactoryImpl.sol +208 -36
- package/{script → src/deployment}/CoinsDeployerBase.sol +111 -17
- package/src/hooks/ZoraV4CoinHook.sol +212 -0
- package/src/hooks/{BaseCoinDeployHook.sol → deployment/BaseCoinDeployHook.sol} +3 -3
- package/src/hooks/deployment/BuySupplyWithSwapRouterHook.sol +140 -0
- package/src/interfaces/ICoin.sol +31 -39
- package/src/interfaces/ICoinV3.sol +71 -0
- package/src/interfaces/ICoinV4.sol +69 -0
- package/src/interfaces/IDeployedCoinVersionLookup.sol +11 -0
- package/src/interfaces/IMsgSender.sol +9 -0
- package/src/interfaces/IPoolConfigEncoding.sol +14 -0
- package/src/interfaces/ISwapPathRouter.sol +14 -0
- package/src/interfaces/IZoraFactory.sol +67 -28
- package/src/interfaces/IZoraV4CoinHook.sol +116 -0
- package/src/libs/CoinCommon.sol +15 -0
- package/src/libs/CoinConfigurationVersions.sol +116 -1
- package/src/libs/CoinConstants.sol +5 -0
- package/src/libs/CoinDopplerMultiCurve.sol +134 -0
- package/src/libs/CoinDopplerUniV3.sol +19 -171
- package/src/libs/CoinRewards.sol +195 -0
- package/src/libs/CoinRewardsV4.sol +179 -0
- package/src/libs/CoinSetup.sol +57 -0
- package/src/libs/CoinSetupV3.sol +6 -67
- package/src/libs/DopplerMath.sol +156 -0
- package/src/libs/HooksDeployment.sol +128 -0
- package/src/libs/MarketConstants.sol +4 -0
- package/src/libs/PoolStateReader.sol +22 -0
- package/src/libs/UniV3BuySell.sol +74 -292
- package/src/libs/UniV4SwapHelper.sol +65 -0
- package/src/libs/UniV4SwapToCurrency.sol +109 -0
- package/src/libs/V4Liquidity.sol +122 -0
- package/src/types/PoolConfiguration.sol +15 -0
- package/src/utils/DeployedCoinVersionLookup.sol +52 -0
- package/src/version/ContractVersionBase.sol +1 -1
- package/test/Coin.t.sol +78 -88
- package/test/CoinDopplerUniV3.t.sol +32 -171
- package/test/CoinUniV4.t.sol +777 -0
- package/test/{Hooks.t.sol → DeploymentHooks.t.sol} +53 -16
- package/test/Factory.t.sol +80 -47
- package/test/MultiOwnable.t.sol +6 -3
- package/test/Upgrades.t.sol +97 -5
- package/test/mocks/MockERC20.sol +12 -0
- package/test/utils/BaseTest.sol +162 -57
- package/test/utils/DeployedCoinVersionLookup.t.sol +127 -0
- package/test/utils/FeeEstimatorHook.sol +84 -0
- package/test/utils/ProxyShim.sol +17 -0
- package/wagmi.config.ts +4 -0
- package/.env +0 -1
- package/.turbo/turbo-update-contract-version.log +0 -22
- package/abis/CoinSetupV3.json +0 -7
- package/abis/HookDeployer.json +0 -68
- package/abis/IHookDeployer.json +0 -42
- package/src/hooks/BuySupplyWithSwapRouterHook.sol +0 -78
- package/src/libs/CoinLegacy.sol +0 -48
- package/src/libs/CoinLegacyMarket.sol +0 -182
package/src/ZoraFactoryImpl.sol
CHANGED
|
@@ -12,21 +12,46 @@ import {CoinConfigurationVersions} from "./libs/CoinConfigurationVersions.sol";
|
|
|
12
12
|
import {ISwapRouter} from "./interfaces/ISwapRouter.sol";
|
|
13
13
|
import {IWETH} from "./interfaces/IWETH.sol";
|
|
14
14
|
import {IZoraFactory} from "./interfaces/IZoraFactory.sol";
|
|
15
|
-
import {IHasAfterCoinDeploy} from "./hooks/BaseCoinDeployHook.sol";
|
|
15
|
+
import {IHasAfterCoinDeploy} from "./hooks/deployment/BaseCoinDeployHook.sol";
|
|
16
16
|
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
17
17
|
import {Coin} from "./Coin.sol";
|
|
18
|
-
import {
|
|
18
|
+
import {CoinV4} from "./CoinV4.sol";
|
|
19
|
+
import {ICoin, PoolKeyStruct} from "./interfaces/ICoin.sol";
|
|
20
|
+
import {ICoinV3} from "./interfaces/ICoinV3.sol";
|
|
21
|
+
import {ICoinV4} from "./interfaces/ICoinV4.sol";
|
|
19
22
|
import {IHasContractName} from "@zoralabs/shared-contracts/interfaces/IContractMetadata.sol";
|
|
20
23
|
import {ContractVersionBase} from "./version/ContractVersionBase.sol";
|
|
24
|
+
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
|
|
25
|
+
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
|
|
26
|
+
import {CoinCommon} from "./libs/CoinCommon.sol";
|
|
27
|
+
import {UniV3Config} from "./libs/CoinSetupV3.sol";
|
|
28
|
+
import {CoinSetupV3} from "./libs/CoinSetupV3.sol";
|
|
29
|
+
import {PoolConfiguration} from "./types/PoolConfiguration.sol";
|
|
30
|
+
import {LpPosition} from "./types/LpPosition.sol";
|
|
31
|
+
import {IVersionedContract} from "@zoralabs/shared-contracts/interfaces/IVersionedContract.sol";
|
|
32
|
+
import {CoinSetup} from "./libs/CoinSetup.sol";
|
|
33
|
+
import {CoinDopplerMultiCurve} from "./libs/CoinDopplerMultiCurve.sol";
|
|
21
34
|
|
|
22
|
-
|
|
35
|
+
import {DeployedCoinVersionLookup} from "./utils/DeployedCoinVersionLookup.sol";
|
|
36
|
+
|
|
37
|
+
contract ZoraFactoryImpl is
|
|
38
|
+
IZoraFactory,
|
|
39
|
+
UUPSUpgradeable,
|
|
40
|
+
ReentrancyGuardUpgradeable,
|
|
41
|
+
OwnableUpgradeable,
|
|
42
|
+
IHasContractName,
|
|
43
|
+
ContractVersionBase,
|
|
44
|
+
DeployedCoinVersionLookup
|
|
45
|
+
{
|
|
23
46
|
using SafeERC20 for IERC20;
|
|
24
47
|
|
|
25
48
|
/// @notice The coin contract implementation address
|
|
26
49
|
address public immutable coinImpl;
|
|
50
|
+
address public immutable coinV4Impl;
|
|
27
51
|
|
|
28
|
-
constructor(address _coinImpl) initializer {
|
|
52
|
+
constructor(address _coinImpl, address _coinV4Impl) initializer {
|
|
29
53
|
coinImpl = _coinImpl;
|
|
54
|
+
coinV4Impl = _coinV4Impl;
|
|
30
55
|
}
|
|
31
56
|
|
|
32
57
|
/// @inheritdoc IZoraFactory
|
|
@@ -38,17 +63,27 @@ contract ZoraFactoryImpl is IZoraFactory, UUPSUpgradeable, ReentrancyGuardUpgrad
|
|
|
38
63
|
string memory symbol,
|
|
39
64
|
bytes memory poolConfig,
|
|
40
65
|
address platformReferrer,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
66
|
+
address postDeployHook,
|
|
67
|
+
bytes calldata postDeployHookData,
|
|
68
|
+
bytes32 coinSalt
|
|
69
|
+
) external payable returns (address coin, bytes memory postDeployHookDataOut) {
|
|
70
|
+
bytes32 salt = _buildSalt(msg.sender, name, symbol, poolConfig, platformReferrer, coinSalt);
|
|
71
|
+
return _deployWithHook(payoutRecipient, owners, uri, name, symbol, poolConfig, platformReferrer, postDeployHook, postDeployHookData, salt);
|
|
72
|
+
}
|
|
46
73
|
|
|
47
|
-
|
|
74
|
+
function coinAddress(
|
|
75
|
+
address msgSender,
|
|
76
|
+
string memory name,
|
|
77
|
+
string memory symbol,
|
|
78
|
+
bytes memory poolConfig,
|
|
79
|
+
address platformReferrer,
|
|
80
|
+
bytes32 coinSalt
|
|
81
|
+
) external view returns (address) {
|
|
82
|
+
bytes32 salt = _buildSalt(msgSender, name, symbol, poolConfig, platformReferrer, coinSalt);
|
|
83
|
+
return Clones.predictDeterministicAddress(getCoinImpl(CoinConfigurationVersions.getVersion(poolConfig)), salt, address(this));
|
|
48
84
|
}
|
|
49
85
|
|
|
50
|
-
|
|
51
|
-
function deployWithHook(
|
|
86
|
+
function _deployWithHook(
|
|
52
87
|
address payoutRecipient,
|
|
53
88
|
address[] memory owners,
|
|
54
89
|
string memory uri,
|
|
@@ -57,9 +92,10 @@ contract ZoraFactoryImpl is IZoraFactory, UUPSUpgradeable, ReentrancyGuardUpgrad
|
|
|
57
92
|
bytes memory poolConfig,
|
|
58
93
|
address platformReferrer,
|
|
59
94
|
address hook,
|
|
60
|
-
bytes calldata hookData
|
|
61
|
-
|
|
62
|
-
|
|
95
|
+
bytes calldata hookData,
|
|
96
|
+
bytes32 salt
|
|
97
|
+
) internal returns (address coin, bytes memory hookDataOut) {
|
|
98
|
+
coin = address(_createAndInitializeCoin(payoutRecipient, owners, uri, name, symbol, poolConfig, platformReferrer, salt));
|
|
63
99
|
|
|
64
100
|
if (hook != address(0)) {
|
|
65
101
|
if (!IERC165(hook).supportsInterface(type(IHasAfterCoinDeploy).interfaceId)) {
|
|
@@ -72,60 +108,195 @@ contract ZoraFactoryImpl is IZoraFactory, UUPSUpgradeable, ReentrancyGuardUpgrad
|
|
|
72
108
|
}
|
|
73
109
|
}
|
|
74
110
|
|
|
75
|
-
|
|
111
|
+
/** Deprecated deploy functions */
|
|
112
|
+
|
|
113
|
+
/// @dev Deprecated: use `deploy` instead that has a salt and hook specified
|
|
76
114
|
function deploy(
|
|
77
115
|
address payoutRecipient,
|
|
78
116
|
address[] memory owners,
|
|
79
117
|
string memory uri,
|
|
80
118
|
string memory name,
|
|
81
119
|
string memory symbol,
|
|
120
|
+
bytes memory poolConfig,
|
|
82
121
|
address platformReferrer,
|
|
83
|
-
address currency,
|
|
84
|
-
int24 tickLower,
|
|
85
122
|
uint256 orderSize
|
|
86
123
|
) public payable nonReentrant returns (address, uint256) {
|
|
87
|
-
|
|
124
|
+
bytes32 salt = _randomSalt(payoutRecipient, uri, bytes32(0));
|
|
88
125
|
|
|
89
|
-
|
|
126
|
+
ICoin coin = _createAndInitializeCoin(payoutRecipient, owners, uri, name, symbol, poolConfig, platformReferrer, salt);
|
|
90
127
|
|
|
91
128
|
uint256 coinsPurchased = _handleFirstOrder(coin, orderSize);
|
|
92
129
|
|
|
93
130
|
return (address(coin), coinsPurchased);
|
|
94
131
|
}
|
|
95
132
|
|
|
96
|
-
|
|
133
|
+
/// @dev Deprecated: use `deploy` instead that has a salt and hook specified
|
|
134
|
+
function deployWithHook(
|
|
97
135
|
address payoutRecipient,
|
|
98
136
|
address[] memory owners,
|
|
99
137
|
string memory uri,
|
|
100
138
|
string memory name,
|
|
101
139
|
string memory symbol,
|
|
102
140
|
bytes memory poolConfig,
|
|
141
|
+
address platformReferrer,
|
|
142
|
+
address hook,
|
|
143
|
+
bytes calldata hookData
|
|
144
|
+
) public payable nonReentrant returns (address coin, bytes memory hookDataOut) {
|
|
145
|
+
bytes32 salt = _randomSalt(payoutRecipient, uri, bytes32(0));
|
|
146
|
+
return _deployWithHook(payoutRecipient, owners, uri, name, symbol, poolConfig, platformReferrer, hook, hookData, salt);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/// @dev deprecated Use deploy() with poolConfig instead
|
|
150
|
+
function deploy(
|
|
151
|
+
address payoutRecipient,
|
|
152
|
+
address[] memory owners,
|
|
153
|
+
string memory uri,
|
|
154
|
+
string memory name,
|
|
155
|
+
string memory symbol,
|
|
156
|
+
address platformReferrer,
|
|
157
|
+
address currency,
|
|
158
|
+
// tickLower is no longer used
|
|
159
|
+
int24 /*tickLower*/,
|
|
160
|
+
uint256 orderSize
|
|
161
|
+
) public payable nonReentrant returns (address, uint256) {
|
|
162
|
+
bytes memory poolConfig = CoinConfigurationVersions.defaultConfig(currency);
|
|
163
|
+
bytes32 salt = _randomSalt(payoutRecipient, uri, bytes32(0));
|
|
164
|
+
|
|
165
|
+
ICoin coin = _createAndInitializeCoin(payoutRecipient, owners, uri, name, symbol, poolConfig, platformReferrer, salt);
|
|
166
|
+
|
|
167
|
+
uint256 coinsPurchased = _handleFirstOrder(coin, orderSize);
|
|
168
|
+
|
|
169
|
+
return (address(coin), coinsPurchased);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function getCoinImpl(uint8 version) internal view returns (address) {
|
|
173
|
+
if (CoinConfigurationVersions.isV3(version)) {
|
|
174
|
+
return coinImpl;
|
|
175
|
+
} else if (CoinConfigurationVersions.isV4(version)) {
|
|
176
|
+
return coinV4Impl;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
revert ICoin.InvalidPoolVersion();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function _createCoin(uint8 version, bytes32 salt) internal returns (address payable) {
|
|
183
|
+
return payable(Clones.cloneDeterministic(getCoinImpl(version), salt));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function _setupV3Coin(
|
|
187
|
+
ICoinV3 coin,
|
|
188
|
+
address currency,
|
|
189
|
+
bool isCoinToken0,
|
|
190
|
+
uint160 sqrtPriceX96,
|
|
191
|
+
PoolConfiguration memory poolConfiguration,
|
|
192
|
+
address payoutRecipient,
|
|
193
|
+
address[] memory owners,
|
|
194
|
+
string memory uri,
|
|
195
|
+
string memory name,
|
|
196
|
+
string memory symbol,
|
|
103
197
|
address platformReferrer
|
|
104
|
-
) internal
|
|
105
|
-
|
|
198
|
+
) internal {
|
|
199
|
+
address v3Factory = coin.v3Factory();
|
|
106
200
|
|
|
107
|
-
|
|
201
|
+
address poolAddress = CoinSetupV3.createV3Pool(address(coin), currency, isCoinToken0, sqrtPriceX96, v3Factory);
|
|
108
202
|
|
|
109
|
-
|
|
203
|
+
LpPosition[] memory positions = CoinDopplerMultiCurve.calculatePositions(isCoinToken0, poolConfiguration);
|
|
204
|
+
|
|
205
|
+
// Initialize coin with pre-configured pool
|
|
206
|
+
coin.initialize(payoutRecipient, owners, uri, name, symbol, platformReferrer, currency, poolAddress, poolConfiguration, positions);
|
|
110
207
|
|
|
111
208
|
emit CoinCreated(
|
|
112
209
|
msg.sender,
|
|
113
210
|
payoutRecipient,
|
|
114
|
-
|
|
115
|
-
|
|
211
|
+
platformReferrer,
|
|
212
|
+
currency,
|
|
116
213
|
uri,
|
|
117
214
|
name,
|
|
118
215
|
symbol,
|
|
119
216
|
address(coin),
|
|
120
|
-
|
|
121
|
-
coin.contractVersion()
|
|
217
|
+
poolAddress,
|
|
218
|
+
IVersionedContract(address(coin)).contractVersion()
|
|
122
219
|
);
|
|
220
|
+
}
|
|
123
221
|
|
|
124
|
-
|
|
222
|
+
function _setupV4Coin(
|
|
223
|
+
ICoinV4 coin,
|
|
224
|
+
address currency,
|
|
225
|
+
bool isCoinToken0,
|
|
226
|
+
uint160 sqrtPriceX96,
|
|
227
|
+
PoolConfiguration memory poolConfiguration,
|
|
228
|
+
address payoutRecipient,
|
|
229
|
+
address[] memory owners,
|
|
230
|
+
string memory uri,
|
|
231
|
+
string memory name,
|
|
232
|
+
string memory symbol,
|
|
233
|
+
address platformReferrer
|
|
234
|
+
) internal {
|
|
235
|
+
PoolKey memory poolKey = CoinSetup.buildPoolKey(address(coin), currency, isCoinToken0, coin.hooks());
|
|
236
|
+
|
|
237
|
+
// Initialize coin with pre-configured pool
|
|
238
|
+
coin.initialize(payoutRecipient, owners, uri, name, symbol, platformReferrer, currency, poolKey, sqrtPriceX96, poolConfiguration);
|
|
239
|
+
|
|
240
|
+
emit CoinCreatedV4(
|
|
241
|
+
msg.sender,
|
|
242
|
+
payoutRecipient,
|
|
243
|
+
platformReferrer,
|
|
244
|
+
currency,
|
|
245
|
+
uri,
|
|
246
|
+
name,
|
|
247
|
+
symbol,
|
|
248
|
+
address(coin),
|
|
249
|
+
poolKey,
|
|
250
|
+
CoinCommon.hashPoolKey(poolKey),
|
|
251
|
+
IVersionedContract(address(coin)).contractVersion()
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function _createAndInitializeCoin(
|
|
256
|
+
address payoutRecipient,
|
|
257
|
+
address[] memory owners,
|
|
258
|
+
string memory uri,
|
|
259
|
+
string memory name,
|
|
260
|
+
string memory symbol,
|
|
261
|
+
bytes memory poolConfig,
|
|
262
|
+
address platformReferrer,
|
|
263
|
+
bytes32 coinSalt
|
|
264
|
+
) internal returns (ICoin) {
|
|
265
|
+
uint8 version = CoinConfigurationVersions.getVersion(poolConfig);
|
|
266
|
+
|
|
267
|
+
address payable coin = _createCoin(version, coinSalt);
|
|
268
|
+
|
|
269
|
+
_setVersionForDeployedCoin(address(coin), version);
|
|
270
|
+
|
|
271
|
+
(, address currency, uint160 sqrtPriceX96, bool isCoinToken0, PoolConfiguration memory poolConfiguration) = CoinSetup.generatePoolConfig(
|
|
272
|
+
address(coin),
|
|
273
|
+
poolConfig
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
if (CoinConfigurationVersions.isV3(version)) {
|
|
277
|
+
_setupV3Coin(ICoinV3(coin), currency, isCoinToken0, sqrtPriceX96, poolConfiguration, payoutRecipient, owners, uri, name, symbol, platformReferrer);
|
|
278
|
+
} else if (CoinConfigurationVersions.isV4(version)) {
|
|
279
|
+
_setupV4Coin(ICoinV4(coin), currency, isCoinToken0, sqrtPriceX96, poolConfiguration, payoutRecipient, owners, uri, name, symbol, platformReferrer);
|
|
280
|
+
} else {
|
|
281
|
+
revert ICoin.InvalidPoolVersion();
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return ICoin(coin);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function _buildSalt(
|
|
288
|
+
address msgSender,
|
|
289
|
+
string memory name,
|
|
290
|
+
string memory symbol,
|
|
291
|
+
bytes memory poolConfig,
|
|
292
|
+
address platformReferrer,
|
|
293
|
+
bytes32 coinSalt
|
|
294
|
+
) internal pure returns (bytes32) {
|
|
295
|
+
return keccak256(abi.encodePacked(msgSender, name, symbol, poolConfig, platformReferrer, coinSalt));
|
|
125
296
|
}
|
|
126
297
|
|
|
127
298
|
/// @dev Generates a unique salt for deterministic deployment
|
|
128
|
-
function
|
|
299
|
+
function _randomSalt(address payoutRecipient, string memory uri, bytes32 coinSalt) internal view returns (bytes32) {
|
|
129
300
|
return
|
|
130
301
|
keccak256(
|
|
131
302
|
abi.encodePacked(
|
|
@@ -137,7 +308,8 @@ contract ZoraFactoryImpl is IZoraFactory, UUPSUpgradeable, ReentrancyGuardUpgrad
|
|
|
137
308
|
block.prevrandao,
|
|
138
309
|
block.timestamp,
|
|
139
310
|
tx.gasprice,
|
|
140
|
-
tx.origin
|
|
311
|
+
tx.origin,
|
|
312
|
+
coinSalt
|
|
141
313
|
)
|
|
142
314
|
);
|
|
143
315
|
}
|
|
@@ -145,12 +317,12 @@ contract ZoraFactoryImpl is IZoraFactory, UUPSUpgradeable, ReentrancyGuardUpgrad
|
|
|
145
317
|
/// @dev Handles the first buy of a newly created coin
|
|
146
318
|
/// @param coin The newly created coin contract
|
|
147
319
|
/// @param orderSize The size of the first buy order; must match msg.value for ETH/WETH pairs
|
|
148
|
-
function _handleFirstOrder(
|
|
320
|
+
function _handleFirstOrder(ICoin coin, uint256 orderSize) internal returns (uint256 coinsPurchased) {
|
|
149
321
|
if (msg.value > 0 || orderSize > 0) {
|
|
150
322
|
address currency = coin.currency();
|
|
151
323
|
address payoutRecipient = coin.payoutRecipient();
|
|
152
324
|
|
|
153
|
-
if (currency != coin.WETH()) {
|
|
325
|
+
if (currency != Coin(payable(address(coin))).WETH()) {
|
|
154
326
|
if (msg.value != 0) {
|
|
155
327
|
revert EthTransferInvalid();
|
|
156
328
|
}
|
|
@@ -159,9 +331,9 @@ contract ZoraFactoryImpl is IZoraFactory, UUPSUpgradeable, ReentrancyGuardUpgrad
|
|
|
159
331
|
|
|
160
332
|
IERC20(currency).approve(address(coin), orderSize);
|
|
161
333
|
|
|
162
|
-
(, coinsPurchased) = coin.buy(payoutRecipient, orderSize, 0, 0, address(0));
|
|
334
|
+
(, coinsPurchased) = Coin(payable(address(coin))).buy(payoutRecipient, orderSize, 0, 0, address(0));
|
|
163
335
|
} else {
|
|
164
|
-
(, coinsPurchased) = coin.buy{value: msg.value}(payoutRecipient, orderSize, 0, 0, address(0));
|
|
336
|
+
(, coinsPurchased) = Coin(payable(address(coin))).buy{value: msg.value}(payoutRecipient, orderSize, 0, 0, address(0));
|
|
165
337
|
}
|
|
166
338
|
}
|
|
167
339
|
}
|
|
@@ -5,14 +5,22 @@ import "forge-std/Script.sol";
|
|
|
5
5
|
|
|
6
6
|
import {ProxyDeployerScript, DeterministicContractConfig, DeterministicDeployerAndCaller} from "@zoralabs/shared-contracts/deployment/ProxyDeployerScript.sol";
|
|
7
7
|
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
|
8
|
-
import {ZoraFactoryImpl} from "../
|
|
9
|
-
import {Coin} from "../
|
|
8
|
+
import {ZoraFactoryImpl} from "../ZoraFactoryImpl.sol";
|
|
9
|
+
import {Coin} from "../Coin.sol";
|
|
10
10
|
import {IVersionedContract} from "@zoralabs/shared-contracts/interfaces/IVersionedContract.sol";
|
|
11
|
-
import {BuySupplyWithSwapRouterHook} from "../
|
|
12
|
-
import {IZoraFactory} from "../
|
|
11
|
+
import {BuySupplyWithSwapRouterHook} from "../hooks/deployment/BuySupplyWithSwapRouterHook.sol";
|
|
12
|
+
import {IZoraFactory} from "../interfaces/IZoraFactory.sol";
|
|
13
|
+
import {CoinV4} from "../CoinV4.sol";
|
|
14
|
+
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
|
|
15
|
+
import {ZoraV4CoinHook} from "../hooks/ZoraV4CoinHook.sol";
|
|
16
|
+
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
|
|
17
|
+
import {ZoraFactory} from "../proxy/ZoraFactory.sol";
|
|
18
|
+
import {HooksDeployment} from "../libs/HooksDeployment.sol";
|
|
19
|
+
import {ProxyShim} from "../../test/utils/ProxyShim.sol";
|
|
13
20
|
|
|
14
21
|
contract CoinsDeployerBase is ProxyDeployerScript {
|
|
15
22
|
address internal constant PROTOCOL_REWARDS = 0x7777777F279eba3d3Ad8F4E708545291A6fDBA8B;
|
|
23
|
+
address internal constant ZORA = 0x1111111111166b7FE7bd91427724B487980aFc69;
|
|
16
24
|
|
|
17
25
|
using stdJson for string;
|
|
18
26
|
|
|
@@ -21,13 +29,25 @@ contract CoinsDeployerBase is ProxyDeployerScript {
|
|
|
21
29
|
address zoraFactory;
|
|
22
30
|
address zoraFactoryImpl;
|
|
23
31
|
// Implementation
|
|
24
|
-
address
|
|
32
|
+
address coinV3Impl;
|
|
33
|
+
address coinV4Impl;
|
|
25
34
|
string coinVersion;
|
|
26
35
|
// hooks
|
|
27
36
|
address buySupplyWithSwapRouterHook;
|
|
37
|
+
address zoraV4CoinHook;
|
|
38
|
+
// Hook deployment salt (for deterministic deployment)
|
|
39
|
+
bytes32 zoraV4CoinHookSalt;
|
|
40
|
+
bool isDev;
|
|
28
41
|
}
|
|
29
42
|
|
|
30
43
|
function addressesFile() internal view returns (string memory) {
|
|
44
|
+
return addressesFile(false);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function addressesFile(bool dev) internal view returns (string memory) {
|
|
48
|
+
if (dev) {
|
|
49
|
+
return string.concat("./addresses/dev/", vm.toString(block.chainid), ".json");
|
|
50
|
+
}
|
|
31
51
|
return string.concat("./addresses/", vm.toString(block.chainid), ".json");
|
|
32
52
|
}
|
|
33
53
|
|
|
@@ -38,13 +58,21 @@ contract CoinsDeployerBase is ProxyDeployerScript {
|
|
|
38
58
|
vm.serializeAddress(objectKey, "ZORA_FACTORY_IMPL", deployment.zoraFactoryImpl);
|
|
39
59
|
vm.serializeString(objectKey, "COIN_VERSION", deployment.coinVersion);
|
|
40
60
|
vm.serializeAddress(objectKey, "BUY_SUPPLY_WITH_SWAP_ROUTER_HOOK", deployment.buySupplyWithSwapRouterHook);
|
|
41
|
-
|
|
61
|
+
vm.serializeAddress(objectKey, "COIN_V3_IMPL", deployment.coinV3Impl);
|
|
62
|
+
vm.serializeAddress(objectKey, "ZORA_V4_COIN_HOOK", deployment.zoraV4CoinHook);
|
|
63
|
+
vm.serializeBytes32(objectKey, "ZORA_V4_COIN_HOOK_SALT", deployment.zoraV4CoinHookSalt);
|
|
64
|
+
string memory result = vm.serializeAddress(objectKey, "COIN_V4_IMPL", deployment.coinV4Impl);
|
|
42
65
|
|
|
43
|
-
vm.writeJson(result, addressesFile());
|
|
66
|
+
vm.writeJson(result, addressesFile(deployment.isDev));
|
|
44
67
|
}
|
|
45
68
|
|
|
46
69
|
function readDeployment() internal returns (CoinsDeployment memory deployment) {
|
|
47
|
-
|
|
70
|
+
return readDeployment(false);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function readDeployment(bool dev) internal returns (CoinsDeployment memory deployment) {
|
|
74
|
+
string memory file = addressesFile(dev);
|
|
75
|
+
deployment.isDev = dev;
|
|
48
76
|
if (!vm.exists(file)) {
|
|
49
77
|
return deployment;
|
|
50
78
|
}
|
|
@@ -52,28 +80,78 @@ contract CoinsDeployerBase is ProxyDeployerScript {
|
|
|
52
80
|
|
|
53
81
|
deployment.zoraFactory = readAddressOrDefaultToZero(json, "ZORA_FACTORY");
|
|
54
82
|
deployment.zoraFactoryImpl = readAddressOrDefaultToZero(json, "ZORA_FACTORY_IMPL");
|
|
55
|
-
deployment.
|
|
83
|
+
deployment.coinV3Impl = readAddressOrDefaultToZero(json, "COIN_V3_IMPL");
|
|
84
|
+
deployment.coinV4Impl = readAddressOrDefaultToZero(json, "COIN_V4_IMPL");
|
|
56
85
|
deployment.coinVersion = readStringOrDefaultToEmpty(json, "COIN_VERSION");
|
|
57
86
|
deployment.buySupplyWithSwapRouterHook = readAddressOrDefaultToZero(json, "BUY_SUPPLY_WITH_SWAP_ROUTER_HOOK");
|
|
87
|
+
deployment.zoraV4CoinHook = readAddressOrDefaultToZero(json, "ZORA_V4_COIN_HOOK");
|
|
88
|
+
deployment.zoraV4CoinHookSalt = readBytes32OrDefaultToZero(json, "ZORA_V4_COIN_HOOK_SALT");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function deployCoinV3Impl() internal returns (Coin) {
|
|
92
|
+
return
|
|
93
|
+
new Coin({
|
|
94
|
+
protocolRewardRecipient_: getZoraRecipient(),
|
|
95
|
+
protocolRewards_: PROTOCOL_REWARDS,
|
|
96
|
+
weth_: getWeth(),
|
|
97
|
+
v3Factory_: getUniswapV3Factory(),
|
|
98
|
+
swapRouter_: getUniswapSwapRouter(),
|
|
99
|
+
airlock_: getDopplerAirlock()
|
|
100
|
+
});
|
|
58
101
|
}
|
|
59
102
|
|
|
60
|
-
function
|
|
61
|
-
return
|
|
103
|
+
function deployCoinV4Impl(address zoraV4CoinHook) internal returns (CoinV4) {
|
|
104
|
+
return
|
|
105
|
+
new CoinV4({
|
|
106
|
+
protocolRewardRecipient_: getZoraRecipient(),
|
|
107
|
+
protocolRewards_: PROTOCOL_REWARDS,
|
|
108
|
+
poolManager_: IPoolManager(getUniswapV4PoolManager()),
|
|
109
|
+
airlock_: getDopplerAirlock(),
|
|
110
|
+
hooks_: IHooks(zoraV4CoinHook)
|
|
111
|
+
});
|
|
62
112
|
}
|
|
63
113
|
|
|
64
|
-
function deployZoraFactoryImpl(address
|
|
65
|
-
return new ZoraFactoryImpl(
|
|
114
|
+
function deployZoraFactoryImpl(address coinV3Impl, address coinV4Impl) internal returns (ZoraFactoryImpl) {
|
|
115
|
+
return new ZoraFactoryImpl(coinV3Impl, coinV4Impl);
|
|
66
116
|
}
|
|
67
117
|
|
|
68
118
|
function deployBuySupplyWithSwapRouterHook(CoinsDeployment memory deployment) internal returns (BuySupplyWithSwapRouterHook) {
|
|
69
|
-
return new BuySupplyWithSwapRouterHook(IZoraFactory(deployment.zoraFactory), getUniswapSwapRouter());
|
|
119
|
+
return new BuySupplyWithSwapRouterHook(IZoraFactory(deployment.zoraFactory), getUniswapSwapRouter(), getUniswapV4PoolManager());
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function deployZoraV4CoinHook(CoinsDeployment memory deployment) internal returns (IHooks, bytes32) {
|
|
123
|
+
// Read existing deployment to get stored salt
|
|
124
|
+
|
|
125
|
+
require(deployment.zoraFactory != address(0), "Zora factory is not set");
|
|
126
|
+
|
|
127
|
+
return
|
|
128
|
+
HooksDeployment.deployZoraV4CoinHookFromScript(
|
|
129
|
+
getUniswapV4PoolManager(),
|
|
130
|
+
deployment.zoraFactory,
|
|
131
|
+
getDefaultTrustedMessageSenders(),
|
|
132
|
+
deployment.zoraV4CoinHookSalt
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function getDefaultTrustedMessageSenders() internal view returns (address[] memory) {
|
|
137
|
+
address[] memory trustedMessageSenders = new address[](2);
|
|
138
|
+
trustedMessageSenders[0] = getUniswapUniversalRouter();
|
|
139
|
+
trustedMessageSenders[1] = getUniswapV4PositionManager();
|
|
140
|
+
return trustedMessageSenders;
|
|
70
141
|
}
|
|
71
142
|
|
|
72
143
|
function deployImpls(CoinsDeployment memory deployment) internal returns (CoinsDeployment memory) {
|
|
73
144
|
// Deploy implementation contracts
|
|
74
|
-
deployment.
|
|
75
|
-
|
|
76
|
-
|
|
145
|
+
deployment.coinV3Impl = address(deployCoinV3Impl());
|
|
146
|
+
|
|
147
|
+
// Deploy hook first, then use its address for coin v4 impl
|
|
148
|
+
(IHooks zoraV4CoinHook, bytes32 usedSalt) = deployZoraV4CoinHook(deployment);
|
|
149
|
+
deployment.zoraV4CoinHook = address(zoraV4CoinHook);
|
|
150
|
+
deployment.zoraV4CoinHookSalt = usedSalt;
|
|
151
|
+
|
|
152
|
+
deployment.coinV4Impl = address(deployCoinV4Impl(deployment.zoraV4CoinHook));
|
|
153
|
+
deployment.zoraFactoryImpl = address(deployZoraFactoryImpl(deployment.coinV3Impl, deployment.coinV4Impl));
|
|
154
|
+
deployment.coinVersion = IVersionedContract(deployment.coinV4Impl).contractVersion();
|
|
77
155
|
deployment.buySupplyWithSwapRouterHook = address(deployBuySupplyWithSwapRouterHook(deployment));
|
|
78
156
|
|
|
79
157
|
return deployment;
|
|
@@ -113,6 +191,22 @@ contract CoinsDeployerBase is ProxyDeployerScript {
|
|
|
113
191
|
require(ZoraFactoryImpl(deployment.zoraFactory).owner() == getProxyAdmin(), "Zora factory owner is not the proxy admin");
|
|
114
192
|
}
|
|
115
193
|
|
|
194
|
+
function deployDevFactory(CoinsDeployment memory deployment) internal returns (ZoraFactory devFactory) {
|
|
195
|
+
address owner = 0x63545B401283c993320A5b886ecF0fc6CB5668a9;
|
|
196
|
+
|
|
197
|
+
ProxyShim shim = new ProxyShim();
|
|
198
|
+
|
|
199
|
+
deployment.zoraFactory = address(new ZoraFactory(address(shim)));
|
|
200
|
+
|
|
201
|
+
deployment = deployImpls(deployment);
|
|
202
|
+
|
|
203
|
+
UUPSUpgradeable(deployment.zoraFactory).upgradeToAndCall(deployment.zoraFactoryImpl, "");
|
|
204
|
+
|
|
205
|
+
ZoraFactoryImpl(deployment.zoraFactory).initialize(owner);
|
|
206
|
+
|
|
207
|
+
saveDeployment(deployment);
|
|
208
|
+
}
|
|
209
|
+
|
|
116
210
|
function printUpgradeFactoryCommand(CoinsDeployment memory deployment) internal view {
|
|
117
211
|
// build upgrade to and call for factory, with init call
|
|
118
212
|
bytes memory call = abi.encodeWithSelector(UUPSUpgradeable.upgradeToAndCall.selector, deployment.zoraFactoryImpl, "");
|