@zoralabs/coins 0.7.1 → 0.9.0
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/.env +1 -0
- package/.turbo/turbo-build.log +114 -109
- package/.turbo/turbo-update-contract-version.log +22 -0
- package/CHANGELOG.md +28 -0
- package/abis/BadImpl.json +15 -0
- package/abis/BalanceDeltaLibrary.json +15 -0
- package/abis/BaseCoin.json +1442 -0
- package/abis/BaseCoinDeployHook.json +78 -0
- package/abis/BaseHook.json +897 -0
- package/abis/BaseTest.json +13 -91
- package/abis/BeforeSwapDeltaLibrary.json +15 -0
- package/abis/BuySupplyWithSwapRouterHook.json +126 -0
- package/abis/Coin.json +48 -92
- package/abis/CoinConstants.json +65 -0
- package/abis/CoinTest.json +13 -91
- package/abis/CoinV4.json +1664 -0
- package/abis/CurrencyLibrary.json +25 -0
- package/abis/DeployHooks.json +9 -0
- package/abis/DopplerUniswapV3Test.json +13 -91
- package/abis/FactoryTest.json +13 -91
- package/abis/FakeHookNoInterface.json +21 -0
- package/abis/HookDeployer.json +68 -0
- package/abis/Hooks.json +28 -0
- package/abis/HooksTest.json +651 -0
- package/abis/IAllowanceTransfer.json +486 -0
- package/abis/ICoin.json +25 -1
- package/abis/ICoinDeployHook.json +31 -0
- package/abis/IContractMetadata.json +28 -0
- package/abis/IEIP712.json +15 -0
- package/abis/IEIP712_v4.json +15 -0
- package/abis/IERC20Minimal.json +172 -0
- package/abis/IERC6909Claims.json +288 -0
- package/abis/IERC721Permit_v4.json +88 -0
- package/abis/IExtsload.json +64 -0
- package/abis/IExttload.json +40 -0
- package/abis/IHasAfterCoinDeploy.json +31 -0
- package/abis/IHasContractName.json +15 -0
- package/abis/IHookDeployer.json +42 -0
- package/abis/IHooks.json +789 -0
- package/abis/IImmutableState.json +15 -0
- package/abis/IMulticall_v4.json +21 -0
- package/abis/INotifier.json +187 -0
- package/abis/IPermit2.json +865 -0
- package/abis/IPermit2Forwarder.json +138 -0
- package/abis/IPoolInitializer_v4.json +53 -0
- package/abis/IPoolManager.json +1286 -0
- package/abis/IPositionManager.json +712 -0
- package/abis/IProtocolFees.json +174 -0
- package/abis/ISignatureTransfer.json +394 -0
- package/abis/ISubscriber.json +89 -0
- package/abis/ISwapRouter.json +82 -0
- package/abis/IUnorderedNonce.json +44 -0
- package/abis/IV4Router.json +47 -0
- package/abis/IZoraFactory.json +144 -0
- package/abis/IZoraV4CoinHook.json +83 -0
- package/abis/ImmutableState.json +36 -0
- package/abis/LPFeeLibrary.json +65 -0
- package/abis/MultiOwnableTest.json +13 -91
- package/abis/Simulate.json +0 -91
- package/abis/UniV3BuySell.json +12 -0
- package/abis/UniV3Errors.json +32 -0
- package/abis/UpgradeFactoryImpl.json +9 -0
- package/abis/UpgradesTest.json +604 -0
- package/abis/ZoraFactoryImpl.json +111 -0
- package/abis/ZoraV4CoinHook.json +989 -0
- package/addresses/8453.json +2 -1
- package/addresses/84532.json +4 -3
- package/dist/index.cjs +125 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +120 -56
- package/dist/index.js.map +1 -1
- package/dist/wagmiGenerated.d.ts +212 -464
- package/dist/wagmiGenerated.d.ts.map +1 -1
- package/package/wagmiGenerated.ts +122 -66
- package/package.json +4 -4
- package/script/CoinsDeployerBase.sol +32 -0
- package/script/DeployHooks.s.sol +22 -0
- package/script/Simulate.s.sol +3 -2
- package/script/UpgradeCoinImpl.sol +2 -2
- package/script/UpgradeFactoryImpl.s.sol +23 -0
- package/src/Coin.sol +35 -342
- package/src/ZoraFactoryImpl.sol +73 -45
- package/src/hooks/BaseCoinDeployHook.sol +62 -0
- package/src/hooks/BuySupplyWithSwapRouterHook.sol +78 -0
- package/src/interfaces/ICoin.sol +5 -1
- package/src/interfaces/ICoinDeployHook.sol +8 -0
- package/src/interfaces/ISwapRouter.sol +1 -35
- package/src/interfaces/IZoraFactory.sol +52 -0
- package/src/{utils → libs}/CoinConstants.sol +6 -6
- package/src/libs/CoinLegacy.sol +4 -4
- package/src/libs/CoinLegacyMarket.sol +182 -0
- package/src/libs/CoinSetupV3.sol +111 -0
- package/src/libs/UniV3BuySell.sol +449 -0
- package/src/libs/UniV3Errors.sol +11 -0
- package/src/version/ContractVersionBase.sol +1 -1
- package/test/Coin.t.sol +20 -17
- package/test/CoinDopplerUniV3.t.sol +7 -17
- package/test/Factory.t.sol +4 -3
- package/test/Hooks.t.sol +274 -0
- package/test/Upgrades.t.sol +67 -0
- package/test/utils/BaseTest.sol +18 -3
- package/wagmi.config.ts +6 -9
- package/src/libs/CoinSetup.sol +0 -37
- /package/abis/{CoinSetup.json → CoinSetupV3.json} +0 -0
package/test/Hooks.t.sol
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.13;
|
|
3
|
+
|
|
4
|
+
import {BaseTest} from "./utils/BaseTest.sol";
|
|
5
|
+
import {BuySupplyWithSwapRouterHook} from "../src/hooks/BuySupplyWithSwapRouterHook.sol";
|
|
6
|
+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
7
|
+
import {IUniswapV3Pool} from "../src/interfaces/IUniswapV3Pool.sol";
|
|
8
|
+
import {Coin} from "../src/Coin.sol";
|
|
9
|
+
import {CoinConfigurationVersions} from "../src/libs/CoinConfigurationVersions.sol";
|
|
10
|
+
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
11
|
+
import {ICoin} from "../src/interfaces/ICoin.sol";
|
|
12
|
+
import {IHasAfterCoinDeploy} from "../src/hooks/BaseCoinDeployHook.sol";
|
|
13
|
+
import {IZoraFactory} from "../src/interfaces/IZoraFactory.sol";
|
|
14
|
+
import {ISwapRouter} from "../src/interfaces/ISwapRouter.sol";
|
|
15
|
+
import {CoinConstants} from "../src/libs/CoinConstants.sol";
|
|
16
|
+
|
|
17
|
+
// Create a fake hook that doesn't support the IHasAfterCoinDeploy interface
|
|
18
|
+
contract FakeHookNoInterface {
|
|
19
|
+
function supportsInterface(bytes4) external pure returns (bool) {
|
|
20
|
+
return false; // Always returns false, doesn't support any interface
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
contract HooksTest is BaseTest {
|
|
25
|
+
int24 internal constant DEFAULT_DISCOVERY_TICK_LOWER = -777000;
|
|
26
|
+
int24 internal constant DEFAULT_DISCOVERY_TICK_UPPER = 222000;
|
|
27
|
+
uint16 internal constant DEFAULT_NUM_DISCOVERY_POSITIONS = 10; // will be 11 total with tail position
|
|
28
|
+
uint256 internal constant DEFAULT_DISCOVERY_SUPPLY_SHARE = 0.495e18; // half of the 990m total pool supply
|
|
29
|
+
address constant zora = 0x1111111111166b7FE7bd91427724B487980aFc69;
|
|
30
|
+
|
|
31
|
+
function _generateDefaultPoolConfig(address currency) internal pure returns (bytes memory) {
|
|
32
|
+
return
|
|
33
|
+
_generatePoolConfig(
|
|
34
|
+
CoinConfigurationVersions.DOPPLER_UNI_V3_POOL_VERSION,
|
|
35
|
+
currency,
|
|
36
|
+
DEFAULT_DISCOVERY_TICK_LOWER,
|
|
37
|
+
DEFAULT_DISCOVERY_TICK_UPPER,
|
|
38
|
+
DEFAULT_NUM_DISCOVERY_POSITIONS,
|
|
39
|
+
DEFAULT_DISCOVERY_SUPPLY_SHARE
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function setUp() public override {
|
|
44
|
+
super.setUpWithBlockNumber(29585474);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function _deployWithHook(address hook, bytes memory hookData, address currency) internal returns (address, bytes memory) {
|
|
48
|
+
bytes memory poolConfig = _generateDefaultPoolConfig(currency);
|
|
49
|
+
return
|
|
50
|
+
factory.deployWithHook(
|
|
51
|
+
users.creator,
|
|
52
|
+
_getDefaultOwners(),
|
|
53
|
+
"https://test.com",
|
|
54
|
+
"Testcoin",
|
|
55
|
+
"TEST",
|
|
56
|
+
poolConfig,
|
|
57
|
+
users.platformReferrer,
|
|
58
|
+
hook,
|
|
59
|
+
hookData
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function _encodeAfterCoinDeploy(address buyRecipient, bytes memory swapRouterCall) internal pure returns (bytes memory) {
|
|
64
|
+
return abi.encode(buyRecipient, swapRouterCall);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function _encodeExactInputSingle(address buyRecipient, ISwapRouter.ExactInputSingleParams memory params) internal pure returns (bytes memory) {
|
|
68
|
+
return _encodeAfterCoinDeploy(buyRecipient, abi.encodeWithSelector(ISwapRouter.exactInputSingle.selector, params));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function _encodeExactInput(address buyRecipient, ISwapRouter.ExactInputParams memory params) internal pure returns (bytes memory) {
|
|
72
|
+
return _encodeAfterCoinDeploy(buyRecipient, abi.encodeWithSelector(ISwapRouter.exactInput.selector, params));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function test_buySupplyWithEthUsingV3Hook_withExactInputSingle(uint256 initialOrderSize) public {
|
|
76
|
+
vm.assume(initialOrderSize > CoinConstants.MIN_ORDER_SIZE);
|
|
77
|
+
vm.assume(initialOrderSize < 1 ether);
|
|
78
|
+
|
|
79
|
+
vm.deal(users.creator, initialOrderSize);
|
|
80
|
+
|
|
81
|
+
BuySupplyWithSwapRouterHook hook = new BuySupplyWithSwapRouterHook(factory, address(swapRouter));
|
|
82
|
+
|
|
83
|
+
bytes memory hookData = _encodeExactInputSingle(
|
|
84
|
+
users.creator,
|
|
85
|
+
ISwapRouter.ExactInputSingleParams({
|
|
86
|
+
tokenIn: address(weth),
|
|
87
|
+
tokenOut: zora,
|
|
88
|
+
fee: 3000,
|
|
89
|
+
recipient: address(hook),
|
|
90
|
+
amountIn: initialOrderSize,
|
|
91
|
+
amountOutMinimum: 0,
|
|
92
|
+
sqrtPriceLimitX96: 0
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
vm.prank(users.creator);
|
|
97
|
+
(address coinAddress, bytes memory hookDataOut) = factory.deployWithHook{value: initialOrderSize}(
|
|
98
|
+
users.creator,
|
|
99
|
+
_getDefaultOwners(),
|
|
100
|
+
"https://test.com",
|
|
101
|
+
"Testcoin",
|
|
102
|
+
"TEST",
|
|
103
|
+
_generateDefaultPoolConfig(zora),
|
|
104
|
+
users.platformReferrer,
|
|
105
|
+
address(hook),
|
|
106
|
+
hookData
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
coin = Coin(payable(coinAddress));
|
|
110
|
+
pool = IUniswapV3Pool(coin.poolAddress());
|
|
111
|
+
|
|
112
|
+
(uint256 amountCurrency, uint256 coinsPurchased) = abi.decode(hookDataOut, (uint256, uint256));
|
|
113
|
+
|
|
114
|
+
assertEq(coin.currency(), zora, "currency");
|
|
115
|
+
assertGt(amountCurrency, 0, "amountCurrency > 0");
|
|
116
|
+
assertGt(coinsPurchased, 0, "coinsPurchased > 0");
|
|
117
|
+
assertEq(coin.balanceOf(users.creator), CoinConstants.CREATOR_LAUNCH_REWARD + coinsPurchased, "balanceOf creator");
|
|
118
|
+
assertGt(IERC20(zora).balanceOf(address(pool)), 0, "Pool ZORA balance");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function test_buySupplyWithEthUsingV3Hook_withExactInputMultiHop(uint256 initialOrderSize) public {
|
|
122
|
+
vm.assume(initialOrderSize > CoinConstants.MIN_ORDER_SIZE);
|
|
123
|
+
vm.assume(initialOrderSize < 1 ether);
|
|
124
|
+
|
|
125
|
+
vm.deal(users.creator, initialOrderSize);
|
|
126
|
+
|
|
127
|
+
// lets try weth to usdc to zora
|
|
128
|
+
|
|
129
|
+
BuySupplyWithSwapRouterHook hook = new BuySupplyWithSwapRouterHook(factory, address(swapRouter));
|
|
130
|
+
|
|
131
|
+
uint24 poolFee = 3000;
|
|
132
|
+
|
|
133
|
+
bytes memory hookData = _encodeExactInput(
|
|
134
|
+
users.creator,
|
|
135
|
+
ISwapRouter.ExactInputParams({
|
|
136
|
+
path: abi.encodePacked(address(weth), poolFee, USDC_ADDRESS, poolFee, zora),
|
|
137
|
+
recipient: address(hook),
|
|
138
|
+
amountIn: initialOrderSize,
|
|
139
|
+
amountOutMinimum: 0
|
|
140
|
+
})
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
vm.prank(users.creator);
|
|
144
|
+
(address coinAddress, bytes memory hookDataOut) = factory.deployWithHook{value: initialOrderSize}(
|
|
145
|
+
users.creator,
|
|
146
|
+
_getDefaultOwners(),
|
|
147
|
+
"https://test.com",
|
|
148
|
+
"Testcoin",
|
|
149
|
+
"TEST",
|
|
150
|
+
_generateDefaultPoolConfig(zora),
|
|
151
|
+
users.platformReferrer,
|
|
152
|
+
address(hook),
|
|
153
|
+
hookData
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
coin = Coin(payable(coinAddress));
|
|
157
|
+
pool = IUniswapV3Pool(coin.poolAddress());
|
|
158
|
+
|
|
159
|
+
(uint256 amountCurrency, uint256 coinsPurchased) = abi.decode(hookDataOut, (uint256, uint256));
|
|
160
|
+
|
|
161
|
+
assertEq(coin.currency(), zora, "currency");
|
|
162
|
+
assertGt(amountCurrency, 0, "amountCurrency > 0");
|
|
163
|
+
assertGt(coinsPurchased, 0, "coinsPurchased > 0");
|
|
164
|
+
assertEq(coin.balanceOf(users.creator), CoinConstants.CREATOR_LAUNCH_REWARD + coinsPurchased, "balanceOf creator");
|
|
165
|
+
assertGt(IERC20(zora).balanceOf(address(pool)), 0, "Pool ZORA balance");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function test_buySupplyWithEthUsingV3Hook_revertsWhenBadCall() public {
|
|
169
|
+
vm.deal(users.creator, 0.0001 ether);
|
|
170
|
+
|
|
171
|
+
BuySupplyWithSwapRouterHook hook = new BuySupplyWithSwapRouterHook(factory, address(swapRouter));
|
|
172
|
+
|
|
173
|
+
uint24 poolFee = 3000;
|
|
174
|
+
|
|
175
|
+
// exact output single is not supported
|
|
176
|
+
bytes memory hookData = _encodeAfterCoinDeploy(
|
|
177
|
+
users.creator,
|
|
178
|
+
abi.encodeWithSelector(
|
|
179
|
+
ISwapRouter.exactOutputSingle.selector,
|
|
180
|
+
ISwapRouter.ExactOutputParams({
|
|
181
|
+
path: abi.encodePacked(address(weth), poolFee, USDC_ADDRESS, poolFee, zora),
|
|
182
|
+
recipient: address(hook),
|
|
183
|
+
amountOut: 0.0001 ether,
|
|
184
|
+
amountInMaximum: 0
|
|
185
|
+
})
|
|
186
|
+
)
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
vm.prank(users.creator);
|
|
190
|
+
vm.expectRevert(BuySupplyWithSwapRouterHook.InvalidSwapRouterCall.selector);
|
|
191
|
+
factory.deployWithHook{value: 0.0001 ether}(
|
|
192
|
+
users.creator,
|
|
193
|
+
_getDefaultOwners(),
|
|
194
|
+
"https://test.com",
|
|
195
|
+
"Testcoin",
|
|
196
|
+
"TEST",
|
|
197
|
+
_generateDefaultPoolConfig(zora),
|
|
198
|
+
users.platformReferrer,
|
|
199
|
+
address(hook),
|
|
200
|
+
hookData
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function test_buySupplyWithEthUsingV3Hook_revertsWhenHookNotRecipient() public {
|
|
205
|
+
uint256 initialOrderSize = 0.0001 ether;
|
|
206
|
+
vm.deal(users.creator, initialOrderSize);
|
|
207
|
+
|
|
208
|
+
BuySupplyWithSwapRouterHook hook = new BuySupplyWithSwapRouterHook(factory, address(swapRouter));
|
|
209
|
+
|
|
210
|
+
bytes memory hookData = _encodeExactInputSingle(
|
|
211
|
+
users.creator,
|
|
212
|
+
ISwapRouter.ExactInputSingleParams({
|
|
213
|
+
tokenIn: address(weth),
|
|
214
|
+
tokenOut: zora,
|
|
215
|
+
fee: 3000,
|
|
216
|
+
recipient: address(users.creator),
|
|
217
|
+
amountIn: initialOrderSize,
|
|
218
|
+
amountOutMinimum: 0,
|
|
219
|
+
sqrtPriceLimitX96: 0
|
|
220
|
+
})
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
vm.prank(users.creator);
|
|
224
|
+
vm.expectRevert(BuySupplyWithSwapRouterHook.Erc20NotReceived.selector);
|
|
225
|
+
factory.deployWithHook{value: initialOrderSize}(
|
|
226
|
+
users.creator,
|
|
227
|
+
_getDefaultOwners(),
|
|
228
|
+
"https://test.com",
|
|
229
|
+
"Testcoin",
|
|
230
|
+
"TEST",
|
|
231
|
+
_generateDefaultPoolConfig(zora),
|
|
232
|
+
users.platformReferrer,
|
|
233
|
+
address(hook),
|
|
234
|
+
hookData
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function test_deployWithHook_revertsWhenEthAndNoHook() public {
|
|
239
|
+
uint256 initialOrderSize = 0.0001 ether;
|
|
240
|
+
vm.deal(users.creator, initialOrderSize);
|
|
241
|
+
|
|
242
|
+
vm.prank(users.creator);
|
|
243
|
+
vm.expectRevert(IZoraFactory.EthTransferInvalid.selector);
|
|
244
|
+
factory.deployWithHook{value: initialOrderSize}(
|
|
245
|
+
users.creator,
|
|
246
|
+
_getDefaultOwners(),
|
|
247
|
+
"https://test.com",
|
|
248
|
+
"Testcoin",
|
|
249
|
+
"TEST",
|
|
250
|
+
_generateDefaultPoolConfig(zora),
|
|
251
|
+
users.platformReferrer,
|
|
252
|
+
address(0),
|
|
253
|
+
""
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function test_invalidHookReverts() public {
|
|
258
|
+
// Deploy a fake hook that doesn't support the IHasAfterCoinDeploy interface
|
|
259
|
+
FakeHookNoInterface fakeHook = new FakeHookNoInterface();
|
|
260
|
+
|
|
261
|
+
bytes memory hookData = "";
|
|
262
|
+
|
|
263
|
+
// Expect the transaction to revert with InvalidHook error
|
|
264
|
+
vm.expectRevert(IZoraFactory.InvalidHook.selector);
|
|
265
|
+
vm.prank(users.creator);
|
|
266
|
+
_deployWithHook(address(fakeHook), hookData, zora);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function test_noHookWorksAsNormal() public {
|
|
270
|
+
// Expect the transaction to revert with InvalidHook error
|
|
271
|
+
vm.prank(users.creator);
|
|
272
|
+
_deployWithHook(address(0), bytes(""), zora);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.13;
|
|
3
|
+
import {Test} from "forge-std/Test.sol";
|
|
4
|
+
import {IZoraFactory} from "../src/interfaces/IZoraFactory.sol";
|
|
5
|
+
import {ZoraFactoryImpl} from "../src/ZoraFactoryImpl.sol";
|
|
6
|
+
|
|
7
|
+
contract BadImpl {
|
|
8
|
+
function contractName() public pure returns (string memory) {
|
|
9
|
+
return "BadImpl";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
contract UpgradesTest is Test {
|
|
14
|
+
ZoraFactoryImpl public factoryProxy;
|
|
15
|
+
|
|
16
|
+
function test_canUpgradeFromVersionWithoutContractName() public {
|
|
17
|
+
// this test that we can upgrade from the current version, which doesn't have a contract name
|
|
18
|
+
vm.createSelectFork("base", 29675508);
|
|
19
|
+
|
|
20
|
+
factoryProxy = ZoraFactoryImpl(0x777777751622c0d3258f214F9DF38E35BF45baF3);
|
|
21
|
+
|
|
22
|
+
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(factoryProxy.implementation());
|
|
23
|
+
|
|
24
|
+
vm.prank(factoryProxy.owner());
|
|
25
|
+
factoryProxy.upgradeToAndCall(address(newImpl), "");
|
|
26
|
+
|
|
27
|
+
assertEq(factoryProxy.implementation(), address(newImpl));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function test_cannotUpgradeToMismatchedContractName() public {
|
|
31
|
+
// this test that we cannot upgrade to a contract with a mismatched contract name
|
|
32
|
+
// once we have upgraded to the version that checks the contract name when upgrading
|
|
33
|
+
vm.createSelectFork("base", 29675508);
|
|
34
|
+
|
|
35
|
+
factoryProxy = ZoraFactoryImpl(0x777777751622c0d3258f214F9DF38E35BF45baF3);
|
|
36
|
+
|
|
37
|
+
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(factoryProxy.implementation());
|
|
38
|
+
|
|
39
|
+
vm.prank(factoryProxy.owner());
|
|
40
|
+
factoryProxy.upgradeToAndCall(address(newImpl), "");
|
|
41
|
+
|
|
42
|
+
BadImpl badImpl = new BadImpl();
|
|
43
|
+
|
|
44
|
+
vm.prank(factoryProxy.owner());
|
|
45
|
+
vm.expectRevert(abi.encodeWithSelector(IZoraFactory.UpgradeToMismatchedContractName.selector, "ZoraCoinFactory", "BadImpl"));
|
|
46
|
+
factoryProxy.upgradeToAndCall(address(badImpl), "");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function test_canUpgradeToSameContractName() public {
|
|
50
|
+
// this test that we can upgrade to the same contract name, when we have already upgraded to a version that has a contract name
|
|
51
|
+
vm.createSelectFork("base", 29675508);
|
|
52
|
+
|
|
53
|
+
factoryProxy = ZoraFactoryImpl(0x777777751622c0d3258f214F9DF38E35BF45baF3);
|
|
54
|
+
|
|
55
|
+
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(factoryProxy.implementation());
|
|
56
|
+
|
|
57
|
+
vm.prank(factoryProxy.owner());
|
|
58
|
+
factoryProxy.upgradeToAndCall(address(newImpl), "");
|
|
59
|
+
|
|
60
|
+
ZoraFactoryImpl newImpl2 = new ZoraFactoryImpl(factoryProxy.implementation());
|
|
61
|
+
|
|
62
|
+
vm.prank(factoryProxy.owner());
|
|
63
|
+
factoryProxy.upgradeToAndCall(address(newImpl2), "");
|
|
64
|
+
|
|
65
|
+
assertEq(factoryProxy.implementation(), address(newImpl2));
|
|
66
|
+
}
|
|
67
|
+
}
|
package/test/utils/BaseTest.sol
CHANGED
|
@@ -12,7 +12,6 @@ import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IER
|
|
|
12
12
|
import {ZoraFactoryImpl} from "../../src/ZoraFactoryImpl.sol";
|
|
13
13
|
import {ZoraFactory} from "../../src/proxy/ZoraFactory.sol";
|
|
14
14
|
import {Coin} from "../../src/Coin.sol";
|
|
15
|
-
import {CoinConstants} from "../../src/utils/CoinConstants.sol";
|
|
16
15
|
import {MultiOwnable} from "../../src/utils/MultiOwnable.sol";
|
|
17
16
|
import {ICoin} from "../../src/interfaces/ICoin.sol";
|
|
18
17
|
import {IERC7572} from "../../src/interfaces/IERC7572.sol";
|
|
@@ -25,7 +24,8 @@ import {IUniswapV3Pool} from "../../src/interfaces/IUniswapV3Pool.sol";
|
|
|
25
24
|
import {IProtocolRewards} from "../../src/interfaces/IProtocolRewards.sol";
|
|
26
25
|
import {ProtocolRewards} from "../utils/ProtocolRewards.sol";
|
|
27
26
|
import {MarketConstants} from "../../src/libs/MarketConstants.sol";
|
|
28
|
-
|
|
27
|
+
|
|
28
|
+
contract BaseTest is Test {
|
|
29
29
|
using stdStorage for StdStorage;
|
|
30
30
|
|
|
31
31
|
address internal constant PROTOCOL_REWARDS = 0x7777777F279eba3d3Ad8F4E708545291A6fDBA8B;
|
|
@@ -65,7 +65,11 @@ contract BaseTest is Test, CoinConstants {
|
|
|
65
65
|
IUniswapV3Pool internal pool;
|
|
66
66
|
|
|
67
67
|
function setUp() public virtual {
|
|
68
|
-
|
|
68
|
+
setUpWithBlockNumber(28415528);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function setUpWithBlockNumber(uint256 forkBlockNumber) public {
|
|
72
|
+
forkId = vm.createSelectFork("base", forkBlockNumber);
|
|
69
73
|
|
|
70
74
|
weth = IWETH(WETH_ADDRESS);
|
|
71
75
|
usdc = IERC20Metadata(USDC_ADDRESS);
|
|
@@ -202,4 +206,15 @@ contract BaseTest is Test, CoinConstants {
|
|
|
202
206
|
function dopplerFeeRecipient() internal view returns (address) {
|
|
203
207
|
return airlock.owner();
|
|
204
208
|
}
|
|
209
|
+
|
|
210
|
+
function _generatePoolConfig(
|
|
211
|
+
uint8 version_,
|
|
212
|
+
address currency_,
|
|
213
|
+
int24 tickLower_,
|
|
214
|
+
int24 tickUpper_,
|
|
215
|
+
uint16 numDiscoveryPositions_,
|
|
216
|
+
uint256 maxDiscoverySupplyShare_
|
|
217
|
+
) internal pure returns (bytes memory) {
|
|
218
|
+
return abi.encode(version_, currency_, tickLower_, tickUpper_, numDiscoveryPositions_, maxDiscoverySupplyShare_);
|
|
219
|
+
}
|
|
205
220
|
}
|
package/wagmi.config.ts
CHANGED
|
@@ -5,18 +5,15 @@ export default defineConfig({
|
|
|
5
5
|
out: "package/wagmiGenerated.ts",
|
|
6
6
|
plugins: [
|
|
7
7
|
foundry({
|
|
8
|
-
deployments: {
|
|
9
|
-
ZoraFactoryImpl: {
|
|
10
|
-
84532: "0x777777751622c0d3258f214F9DF38E35BF45baF3",
|
|
11
|
-
8453: "0x777777751622c0d3258f214F9DF38E35BF45baF3",
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
8
|
forge: {
|
|
15
9
|
build: false,
|
|
16
10
|
},
|
|
17
|
-
include: [
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
include: [
|
|
12
|
+
"Coin",
|
|
13
|
+
"ZoraFactoryImpl",
|
|
14
|
+
"IUniswapV3Pool",
|
|
15
|
+
"BuySupplyWithSwapRouterHook",
|
|
16
|
+
].map((contractName) => `${contractName}.json`),
|
|
20
17
|
}),
|
|
21
18
|
],
|
|
22
19
|
});
|
package/src/libs/CoinSetup.sol
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.23;
|
|
3
|
-
|
|
4
|
-
import {PoolConfiguration} from "../interfaces/ICoin.sol";
|
|
5
|
-
import {CoinLegacy} from "./CoinLegacy.sol";
|
|
6
|
-
import {CoinDopplerUniV3} from "./CoinDopplerUniV3.sol";
|
|
7
|
-
import {CoinConfigurationVersions} from "./CoinConfigurationVersions.sol";
|
|
8
|
-
import {LpPosition} from "../types/LpPosition.sol";
|
|
9
|
-
|
|
10
|
-
library CoinSetup {
|
|
11
|
-
error InvalidPoolVersion();
|
|
12
|
-
|
|
13
|
-
function setupPoolWithVersion(
|
|
14
|
-
uint8 version,
|
|
15
|
-
bytes memory poolConfig_,
|
|
16
|
-
bool isCoinToken0,
|
|
17
|
-
address weth
|
|
18
|
-
) internal pure returns (uint160 sqrtPriceX96, PoolConfiguration memory poolConfiguration) {
|
|
19
|
-
if (version == CoinConfigurationVersions.LEGACY_POOL_VERSION) {
|
|
20
|
-
(sqrtPriceX96, poolConfiguration) = CoinLegacy.setupPool(isCoinToken0, poolConfig_, weth);
|
|
21
|
-
} else if (version == CoinConfigurationVersions.DOPPLER_UNI_V3_POOL_VERSION) {
|
|
22
|
-
(sqrtPriceX96, poolConfiguration) = CoinDopplerUniV3.setupPool(isCoinToken0, poolConfig_);
|
|
23
|
-
} else {
|
|
24
|
-
revert InvalidPoolVersion();
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function calculatePositions(bool isCoinToken0, PoolConfiguration memory poolConfiguration) internal pure returns (LpPosition[] memory positions) {
|
|
29
|
-
if (poolConfiguration.version == CoinConfigurationVersions.LEGACY_POOL_VERSION) {
|
|
30
|
-
positions = CoinLegacy.calculatePositions(isCoinToken0, poolConfiguration);
|
|
31
|
-
} else if (poolConfiguration.version == CoinConfigurationVersions.DOPPLER_UNI_V3_POOL_VERSION) {
|
|
32
|
-
positions = CoinDopplerUniV3.calculatePositions(isCoinToken0, poolConfiguration);
|
|
33
|
-
} else {
|
|
34
|
-
revert InvalidPoolVersion();
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
File without changes
|