@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
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
pragma solidity ^0.8.13;
|
|
3
3
|
|
|
4
4
|
import {BaseTest} from "./utils/BaseTest.sol";
|
|
5
|
-
import {BuySupplyWithSwapRouterHook} from "../src/hooks/BuySupplyWithSwapRouterHook.sol";
|
|
5
|
+
import {BuySupplyWithSwapRouterHook} from "../src/hooks/deployment/BuySupplyWithSwapRouterHook.sol";
|
|
6
6
|
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
7
7
|
import {IUniswapV3Pool} from "../src/interfaces/IUniswapV3Pool.sol";
|
|
8
8
|
import {Coin} from "../src/Coin.sol";
|
|
9
9
|
import {CoinConfigurationVersions} from "../src/libs/CoinConfigurationVersions.sol";
|
|
10
10
|
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
11
11
|
import {ICoin} from "../src/interfaces/ICoin.sol";
|
|
12
|
-
import {IHasAfterCoinDeploy} from "../src/hooks/BaseCoinDeployHook.sol";
|
|
12
|
+
import {IHasAfterCoinDeploy} from "../src/hooks/deployment/BaseCoinDeployHook.sol";
|
|
13
13
|
import {IZoraFactory} from "../src/interfaces/IZoraFactory.sol";
|
|
14
14
|
import {ISwapRouter} from "../src/interfaces/ISwapRouter.sol";
|
|
15
15
|
import {CoinConstants} from "../src/libs/CoinConstants.sol";
|
|
@@ -22,11 +22,8 @@ contract FakeHookNoInterface {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
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
25
|
address constant zora = 0x1111111111166b7FE7bd91427724B487980aFc69;
|
|
26
|
+
BuySupplyWithSwapRouterHook hook;
|
|
30
27
|
|
|
31
28
|
function _generateDefaultPoolConfig(address currency) internal pure returns (bytes memory) {
|
|
32
29
|
return
|
|
@@ -42,9 +39,11 @@ contract HooksTest is BaseTest {
|
|
|
42
39
|
|
|
43
40
|
function setUp() public override {
|
|
44
41
|
super.setUpWithBlockNumber(29585474);
|
|
42
|
+
|
|
43
|
+
hook = new BuySupplyWithSwapRouterHook(factory, address(swapRouter), address(V4_POOL_MANAGER));
|
|
45
44
|
}
|
|
46
45
|
|
|
47
|
-
function _deployWithHook(address
|
|
46
|
+
function _deployWithHook(address _hook, bytes memory hookData, address currency) internal returns (address, bytes memory) {
|
|
48
47
|
bytes memory poolConfig = _generateDefaultPoolConfig(currency);
|
|
49
48
|
return
|
|
50
49
|
factory.deployWithHook(
|
|
@@ -55,7 +54,7 @@ contract HooksTest is BaseTest {
|
|
|
55
54
|
"TEST",
|
|
56
55
|
poolConfig,
|
|
57
56
|
users.platformReferrer,
|
|
58
|
-
|
|
57
|
+
_hook,
|
|
59
58
|
hookData
|
|
60
59
|
);
|
|
61
60
|
}
|
|
@@ -78,8 +77,6 @@ contract HooksTest is BaseTest {
|
|
|
78
77
|
|
|
79
78
|
vm.deal(users.creator, initialOrderSize);
|
|
80
79
|
|
|
81
|
-
BuySupplyWithSwapRouterHook hook = new BuySupplyWithSwapRouterHook(factory, address(swapRouter));
|
|
82
|
-
|
|
83
80
|
bytes memory hookData = _encodeExactInputSingle(
|
|
84
81
|
users.creator,
|
|
85
82
|
ISwapRouter.ExactInputSingleParams({
|
|
@@ -118,7 +115,7 @@ contract HooksTest is BaseTest {
|
|
|
118
115
|
assertGt(IERC20(zora).balanceOf(address(pool)), 0, "Pool ZORA balance");
|
|
119
116
|
}
|
|
120
117
|
|
|
121
|
-
function
|
|
118
|
+
function test_buySupplyWithEthUsingV4Hook_withExactInputMultiHop(uint256 initialOrderSize) public {
|
|
122
119
|
vm.assume(initialOrderSize > CoinConstants.MIN_ORDER_SIZE);
|
|
123
120
|
vm.assume(initialOrderSize < 1 ether);
|
|
124
121
|
|
|
@@ -126,7 +123,51 @@ contract HooksTest is BaseTest {
|
|
|
126
123
|
|
|
127
124
|
// lets try weth to usdc to zora
|
|
128
125
|
|
|
129
|
-
|
|
126
|
+
uint24 poolFee = 3000;
|
|
127
|
+
|
|
128
|
+
bytes memory hookData = _encodeExactInput(
|
|
129
|
+
users.creator,
|
|
130
|
+
ISwapRouter.ExactInputParams({
|
|
131
|
+
path: abi.encodePacked(address(weth), poolFee, USDC_ADDRESS, poolFee, zora),
|
|
132
|
+
recipient: address(hook),
|
|
133
|
+
amountIn: initialOrderSize,
|
|
134
|
+
amountOutMinimum: 0
|
|
135
|
+
})
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
bytes memory poolConfig = CoinConfigurationVersions.defaultDopplerMultiCurveUniV4(zora);
|
|
139
|
+
|
|
140
|
+
vm.prank(users.creator);
|
|
141
|
+
(address coinAddress, bytes memory hookDataOut) = factory.deployWithHook{value: initialOrderSize}(
|
|
142
|
+
users.creator,
|
|
143
|
+
_getDefaultOwners(),
|
|
144
|
+
"https://test.com",
|
|
145
|
+
"Testcoin",
|
|
146
|
+
"TEST",
|
|
147
|
+
poolConfig,
|
|
148
|
+
users.platformReferrer,
|
|
149
|
+
address(hook),
|
|
150
|
+
hookData
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
coin = Coin(payable(coinAddress));
|
|
154
|
+
|
|
155
|
+
(uint256 amountCurrency, uint256 coinsPurchased) = abi.decode(hookDataOut, (uint256, uint256));
|
|
156
|
+
|
|
157
|
+
assertEq(coin.currency(), zora, "currency");
|
|
158
|
+
assertGt(amountCurrency, 0, "amountCurrency > 0");
|
|
159
|
+
assertGt(coinsPurchased, 0, "coinsPurchased > 0");
|
|
160
|
+
assertEq(coin.balanceOf(users.creator), CoinConstants.CREATOR_LAUNCH_REWARD + coinsPurchased, "balanceOf creator");
|
|
161
|
+
// assertGt(IERC20(zora).balanceOf(address(pool)), 0, "Pool ZORA balance");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function test_buySupplyWithEthUsingV3Hook_withExactInputMultiHop(uint256 initialOrderSize) public {
|
|
165
|
+
vm.assume(initialOrderSize > CoinConstants.MIN_ORDER_SIZE);
|
|
166
|
+
vm.assume(initialOrderSize < 1 ether);
|
|
167
|
+
|
|
168
|
+
vm.deal(users.creator, initialOrderSize);
|
|
169
|
+
|
|
170
|
+
// lets try weth to usdc to zora
|
|
130
171
|
|
|
131
172
|
uint24 poolFee = 3000;
|
|
132
173
|
|
|
@@ -168,8 +209,6 @@ contract HooksTest is BaseTest {
|
|
|
168
209
|
function test_buySupplyWithEthUsingV3Hook_revertsWhenBadCall() public {
|
|
169
210
|
vm.deal(users.creator, 0.0001 ether);
|
|
170
211
|
|
|
171
|
-
BuySupplyWithSwapRouterHook hook = new BuySupplyWithSwapRouterHook(factory, address(swapRouter));
|
|
172
|
-
|
|
173
212
|
uint24 poolFee = 3000;
|
|
174
213
|
|
|
175
214
|
// exact output single is not supported
|
|
@@ -205,8 +244,6 @@ contract HooksTest is BaseTest {
|
|
|
205
244
|
uint256 initialOrderSize = 0.0001 ether;
|
|
206
245
|
vm.deal(users.creator, initialOrderSize);
|
|
207
246
|
|
|
208
|
-
BuySupplyWithSwapRouterHook hook = new BuySupplyWithSwapRouterHook(factory, address(swapRouter));
|
|
209
|
-
|
|
210
247
|
bytes memory hookData = _encodeExactInputSingle(
|
|
211
248
|
users.creator,
|
|
212
249
|
ISwapRouter.ExactInputSingleParams({
|
package/test/Factory.t.sol
CHANGED
|
@@ -10,8 +10,9 @@ contract FactoryTest is BaseTest {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
function test_constructor() public view {
|
|
13
|
-
assertEq(factory.coinImpl(), address(
|
|
14
|
-
assertEq(factory.owner(), users.factoryOwner);
|
|
13
|
+
assertEq(ZoraFactoryImpl(address(factory)).coinImpl(), address(coinV3Impl));
|
|
14
|
+
assertEq(ZoraFactoryImpl(address(factory)).owner(), users.factoryOwner);
|
|
15
|
+
assertEq(ZoraFactoryImpl(address(factory)).coinV4Impl(), address(coinV4Impl));
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
function test_deploy_no_eth() public {
|
|
@@ -24,9 +25,8 @@ contract FactoryTest is BaseTest {
|
|
|
24
25
|
"https://test2.com",
|
|
25
26
|
"Test2 Token",
|
|
26
27
|
"TEST2",
|
|
28
|
+
_generatePoolConfig(address(weth)),
|
|
27
29
|
users.platformReferrer,
|
|
28
|
-
address(weth),
|
|
29
|
-
MarketConstants.LP_TICK_LOWER_WETH,
|
|
30
30
|
0
|
|
31
31
|
);
|
|
32
32
|
coin = Coin(payable(coinAddress));
|
|
@@ -73,9 +73,8 @@ contract FactoryTest is BaseTest {
|
|
|
73
73
|
"https://test2.com",
|
|
74
74
|
"Test2 Token",
|
|
75
75
|
"TEST2",
|
|
76
|
+
_generatePoolConfig(address(weth)),
|
|
76
77
|
users.platformReferrer,
|
|
77
|
-
address(weth),
|
|
78
|
-
MarketConstants.LP_TICK_LOWER_WETH,
|
|
79
78
|
initialOrderSize
|
|
80
79
|
);
|
|
81
80
|
coin = Coin(payable(coinAddress));
|
|
@@ -119,9 +118,8 @@ contract FactoryTest is BaseTest {
|
|
|
119
118
|
"https://test2.com",
|
|
120
119
|
"Test2 Token",
|
|
121
120
|
"TEST2",
|
|
121
|
+
_generatePoolConfig(address(weth)),
|
|
122
122
|
users.platformReferrer,
|
|
123
|
-
address(weth),
|
|
124
|
-
MarketConstants.LP_TICK_LOWER_WETH,
|
|
125
123
|
initialOrderSize
|
|
126
124
|
);
|
|
127
125
|
}
|
|
@@ -139,9 +137,8 @@ contract FactoryTest is BaseTest {
|
|
|
139
137
|
"https://test2.com",
|
|
140
138
|
"Test2 Token",
|
|
141
139
|
"TEST2",
|
|
140
|
+
_generatePoolConfig(address(weth)),
|
|
142
141
|
users.platformReferrer,
|
|
143
|
-
address(weth),
|
|
144
|
-
MarketConstants.LP_TICK_LOWER_WETH,
|
|
145
142
|
orderSize
|
|
146
143
|
);
|
|
147
144
|
coin = Coin(payable(coinAddress));
|
|
@@ -160,9 +157,8 @@ contract FactoryTest is BaseTest {
|
|
|
160
157
|
"https://testcoinusdcpair.com",
|
|
161
158
|
"Testcoinusdcpair",
|
|
162
159
|
"TESTCOINUSDCPAIR",
|
|
160
|
+
_generatePoolConfig(USDC_ADDRESS),
|
|
163
161
|
users.platformReferrer,
|
|
164
|
-
USDC_ADDRESS,
|
|
165
|
-
USDC_TICK_LOWER,
|
|
166
162
|
0
|
|
167
163
|
);
|
|
168
164
|
coin = Coin(payable(coinAddress));
|
|
@@ -193,9 +189,8 @@ contract FactoryTest is BaseTest {
|
|
|
193
189
|
"https://testcoinusdcpair.com",
|
|
194
190
|
"Testcoinusdcpair",
|
|
195
191
|
"TESTCOINUSDCPAIR",
|
|
192
|
+
_generatePoolConfig(USDC_ADDRESS),
|
|
196
193
|
users.platformReferrer,
|
|
197
|
-
USDC_ADDRESS,
|
|
198
|
-
USDC_TICK_LOWER,
|
|
199
194
|
orderSize
|
|
200
195
|
);
|
|
201
196
|
coin = Coin(payable(coinAddress));
|
|
@@ -218,9 +213,8 @@ contract FactoryTest is BaseTest {
|
|
|
218
213
|
"https://testcoinusdcpair.com",
|
|
219
214
|
"Testcoinusdcpair",
|
|
220
215
|
"TESTCOINUSDCPAIR",
|
|
216
|
+
_generatePoolConfig(USDC_ADDRESS),
|
|
221
217
|
users.platformReferrer,
|
|
222
|
-
USDC_ADDRESS,
|
|
223
|
-
USDC_TICK_LOWER,
|
|
224
218
|
0
|
|
225
219
|
);
|
|
226
220
|
}
|
|
@@ -235,9 +229,8 @@ contract FactoryTest is BaseTest {
|
|
|
235
229
|
"https://testcoinusdcpair.com",
|
|
236
230
|
"Testcoinusdcpair",
|
|
237
231
|
"TESTCOINUSDCPAIR",
|
|
232
|
+
_generatePoolConfig(USDC_ADDRESS),
|
|
238
233
|
users.platformReferrer,
|
|
239
|
-
USDC_ADDRESS,
|
|
240
|
-
USDC_TICK_LOWER,
|
|
241
234
|
0
|
|
242
235
|
);
|
|
243
236
|
}
|
|
@@ -252,9 +245,8 @@ contract FactoryTest is BaseTest {
|
|
|
252
245
|
"https://testcoinusdcpair.com",
|
|
253
246
|
"Testcoinusdcpair",
|
|
254
247
|
"TESTCOINUSDCPAIR",
|
|
248
|
+
_generatePoolConfig(USDC_ADDRESS),
|
|
255
249
|
address(0),
|
|
256
|
-
USDC_ADDRESS,
|
|
257
|
-
USDC_TICK_LOWER,
|
|
258
250
|
0
|
|
259
251
|
);
|
|
260
252
|
|
|
@@ -263,24 +255,6 @@ contract FactoryTest is BaseTest {
|
|
|
263
255
|
assertEq(coin.platformReferrer(), coin.protocolRewardRecipient(), "platformReferrer");
|
|
264
256
|
}
|
|
265
257
|
|
|
266
|
-
function test_revert_deploy_with_invalid_currency_tick() public {
|
|
267
|
-
address[] memory owners = new address[](1);
|
|
268
|
-
owners[0] = users.creator;
|
|
269
|
-
|
|
270
|
-
vm.expectRevert(abi.encodeWithSelector(ICoin.InvalidWethLowerTick.selector));
|
|
271
|
-
factory.deploy(
|
|
272
|
-
users.creator,
|
|
273
|
-
owners,
|
|
274
|
-
"https://testcoin.com",
|
|
275
|
-
"Testcoin",
|
|
276
|
-
"TESTCOIN",
|
|
277
|
-
users.platformReferrer,
|
|
278
|
-
address(0),
|
|
279
|
-
MarketConstants.LP_TICK_LOWER_WETH + 1,
|
|
280
|
-
0
|
|
281
|
-
);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
258
|
function test_deploy_with_usdc_revert_invalid_eth_transfer() public {
|
|
285
259
|
address[] memory owners = new address[](1);
|
|
286
260
|
owners[0] = users.creator;
|
|
@@ -298,9 +272,8 @@ contract FactoryTest is BaseTest {
|
|
|
298
272
|
"https://testcoinusdcpair.com",
|
|
299
273
|
"Testcoinusdcpair",
|
|
300
274
|
"TESTCOINUSDCPAIR",
|
|
275
|
+
_generatePoolConfig(USDC_ADDRESS),
|
|
301
276
|
users.platformReferrer,
|
|
302
|
-
USDC_ADDRESS,
|
|
303
|
-
USDC_TICK_LOWER,
|
|
304
277
|
0
|
|
305
278
|
);
|
|
306
279
|
}
|
|
@@ -315,9 +288,8 @@ contract FactoryTest is BaseTest {
|
|
|
315
288
|
"https://test.com",
|
|
316
289
|
"Test Token",
|
|
317
290
|
"TEST",
|
|
291
|
+
_generatePoolConfig(address(weth)),
|
|
318
292
|
users.platformReferrer,
|
|
319
|
-
address(weth),
|
|
320
|
-
MarketConstants.LP_TICK_LOWER_WETH,
|
|
321
293
|
0
|
|
322
294
|
);
|
|
323
295
|
coin = Coin(payable(coinAddress));
|
|
@@ -326,10 +298,10 @@ contract FactoryTest is BaseTest {
|
|
|
326
298
|
}
|
|
327
299
|
|
|
328
300
|
function test_upgrade() public {
|
|
329
|
-
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(address(
|
|
301
|
+
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(address(coinV3Impl), address(coinV4Impl));
|
|
330
302
|
|
|
331
303
|
vm.prank(users.factoryOwner);
|
|
332
|
-
factory.upgradeToAndCall(address(newImpl), "");
|
|
304
|
+
ZoraFactoryImpl(address(factory)).upgradeToAndCall(address(newImpl), "");
|
|
333
305
|
|
|
334
306
|
assertEq(factory.implementation(), address(newImpl), "implementation");
|
|
335
307
|
}
|
|
@@ -343,14 +315,75 @@ contract FactoryTest is BaseTest {
|
|
|
343
315
|
|
|
344
316
|
vm.prank(users.factoryOwner);
|
|
345
317
|
vm.expectRevert(abi.encodeWithSelector(ERC1967Utils.ERC1967InvalidImplementation.selector, address(newImpl)));
|
|
346
|
-
factory.upgradeToAndCall(address(newImpl), "");
|
|
318
|
+
ZoraFactoryImpl(address(factory)).upgradeToAndCall(address(newImpl), "");
|
|
347
319
|
}
|
|
348
320
|
|
|
349
321
|
function test_revert_invalid_owner() public {
|
|
350
|
-
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(address(
|
|
322
|
+
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(address(coinV3Impl), address(coinV4Impl));
|
|
351
323
|
|
|
352
324
|
vm.prank(users.creator);
|
|
353
325
|
vm.expectRevert(abi.encodeWithSelector(OwnableUpgradeable.OwnableUnauthorizedAccount.selector, users.creator));
|
|
354
|
-
factory.upgradeToAndCall(address(newImpl), "");
|
|
326
|
+
ZoraFactoryImpl(address(factory)).upgradeToAndCall(address(newImpl), "");
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function test_coinAddress_canBePredicted(
|
|
330
|
+
bool msgSenderChanged,
|
|
331
|
+
bool saltChanged,
|
|
332
|
+
bool poolConfigChanged,
|
|
333
|
+
bool platformReferrerChanged,
|
|
334
|
+
bool nameChanged,
|
|
335
|
+
bool symbolChanged
|
|
336
|
+
) public {
|
|
337
|
+
address[] memory owners = new address[](1);
|
|
338
|
+
owners[0] = users.creator;
|
|
339
|
+
|
|
340
|
+
address payoutRecipient = users.creator;
|
|
341
|
+
|
|
342
|
+
bytes32 salt = keccak256(abi.encode(bytes("randomSalt")));
|
|
343
|
+
|
|
344
|
+
address msgSender = makeAddr("msgSender");
|
|
345
|
+
|
|
346
|
+
string memory uri = "https://test.com";
|
|
347
|
+
string memory name = "Testcoin";
|
|
348
|
+
string memory symbol = "TEST";
|
|
349
|
+
|
|
350
|
+
address platformReferrer = users.platformReferrer;
|
|
351
|
+
|
|
352
|
+
bytes memory poolConfig = CoinConfigurationVersions.defaultDopplerMultiCurveUniV4(address(weth));
|
|
353
|
+
bytes memory poolConfigForGettingAddress = poolConfigChanged ? CoinConfigurationVersions.defaultDopplerUniV3(address(weth)) : poolConfig;
|
|
354
|
+
|
|
355
|
+
address expectedCoinAddress = factory.coinAddress(msgSender, name, symbol, poolConfigForGettingAddress, platformReferrer, salt);
|
|
356
|
+
|
|
357
|
+
if (msgSenderChanged) {
|
|
358
|
+
msgSender = makeAddr("msgSender2");
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (saltChanged) {
|
|
362
|
+
salt = keccak256(abi.encode(bytes("randomSalt2")));
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (platformReferrerChanged) {
|
|
366
|
+
platformReferrer = makeAddr("platformReferrer2");
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
if (nameChanged) {
|
|
370
|
+
name = "Testcoin2";
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (symbolChanged) {
|
|
374
|
+
symbol = "TEST2";
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// now deploy the coin
|
|
378
|
+
vm.prank(msgSender);
|
|
379
|
+
(address coinAddress, ) = factory.deploy(payoutRecipient, owners, uri, name, symbol, poolConfig, platformReferrer, address(0), bytes(""), salt);
|
|
380
|
+
|
|
381
|
+
bool addressShouldMismatch = msgSenderChanged || saltChanged || poolConfigChanged || platformReferrerChanged || nameChanged || symbolChanged;
|
|
382
|
+
|
|
383
|
+
if (addressShouldMismatch) {
|
|
384
|
+
assertNotEq(coinAddress, expectedCoinAddress, "coinAddress should mismatch");
|
|
385
|
+
} else {
|
|
386
|
+
assertEq(coinAddress, expectedCoinAddress, "coinAddress should match");
|
|
387
|
+
}
|
|
355
388
|
}
|
|
356
389
|
}
|
package/test/MultiOwnable.t.sol
CHANGED
|
@@ -135,22 +135,25 @@ contract MultiOwnableTest is BaseTest {
|
|
|
135
135
|
|
|
136
136
|
function test_revert_init_with_zero_owners() public {
|
|
137
137
|
address[] memory emptyOwners = new address[](0);
|
|
138
|
+
bytes memory poolConfig_ = _generatePoolConfig(address(weth));
|
|
138
139
|
vm.expectRevert(MultiOwnable.OneOwnerRequired.selector);
|
|
139
|
-
factory.deploy(users.creator, emptyOwners, "https://test.com", "Test Token", "TEST", users.platformReferrer,
|
|
140
|
+
factory.deploy(users.creator, emptyOwners, "https://test.com", "Test Token", "TEST", poolConfig_, users.platformReferrer, 0);
|
|
140
141
|
}
|
|
141
142
|
|
|
142
143
|
function test_revert_init_with_zero_address() public {
|
|
143
144
|
address[] memory owners = new address[](1);
|
|
144
145
|
owners[0] = address(0);
|
|
146
|
+
bytes memory poolConfig_ = _generatePoolConfig(address(weth));
|
|
145
147
|
vm.expectRevert(MultiOwnable.OwnerCannotBeAddressZero.selector);
|
|
146
|
-
factory.deploy(users.creator, owners, "https://test.com", "Test Token", "TEST", users.platformReferrer,
|
|
148
|
+
factory.deploy(users.creator, owners, "https://test.com", "Test Token", "TEST", poolConfig_, users.platformReferrer, 0);
|
|
147
149
|
}
|
|
148
150
|
|
|
149
151
|
function test_revert_init_with_duplicate_owner() public {
|
|
150
152
|
address[] memory owners = new address[](2);
|
|
151
153
|
owners[0] = users.creator;
|
|
152
154
|
owners[1] = users.creator;
|
|
155
|
+
bytes memory poolConfig_ = _generatePoolConfig(address(weth));
|
|
153
156
|
vm.expectRevert(MultiOwnable.AlreadyOwner.selector);
|
|
154
|
-
factory.deploy(users.creator, owners, "https://test.com", "Test Token", "TEST", users.platformReferrer,
|
|
157
|
+
factory.deploy(users.creator, owners, "https://test.com", "Test Token", "TEST", poolConfig_, users.platformReferrer, 0);
|
|
155
158
|
}
|
|
156
159
|
}
|
package/test/Upgrades.t.sol
CHANGED
|
@@ -3,6 +3,18 @@ pragma solidity ^0.8.13;
|
|
|
3
3
|
import {Test} from "forge-std/Test.sol";
|
|
4
4
|
import {IZoraFactory} from "../src/interfaces/IZoraFactory.sol";
|
|
5
5
|
import {ZoraFactoryImpl} from "../src/ZoraFactoryImpl.sol";
|
|
6
|
+
import {BaseTest} from "./utils/BaseTest.sol";
|
|
7
|
+
import {CoinsDeployerBase} from "../src/deployment/CoinsDeployerBase.sol";
|
|
8
|
+
import {CoinConfigurationVersions} from "../src/libs/CoinConfigurationVersions.sol";
|
|
9
|
+
import {ICoinV4} from "../src/interfaces/ICoinV4.sol";
|
|
10
|
+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
11
|
+
import {ISwapRouter} from "../src/interfaces/ISwapRouter.sol";
|
|
12
|
+
import {IWETH} from "../src/interfaces/IWETH.sol";
|
|
13
|
+
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
|
|
14
|
+
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
|
|
15
|
+
import {BuySupplyWithSwapRouterHook} from "../src/hooks/deployment/BuySupplyWithSwapRouterHook.sol";
|
|
16
|
+
|
|
17
|
+
import {console} from "forge-std/console.sol";
|
|
6
18
|
|
|
7
19
|
contract BadImpl {
|
|
8
20
|
function contractName() public pure returns (string memory) {
|
|
@@ -10,7 +22,7 @@ contract BadImpl {
|
|
|
10
22
|
}
|
|
11
23
|
}
|
|
12
24
|
|
|
13
|
-
contract UpgradesTest is
|
|
25
|
+
contract UpgradesTest is BaseTest, CoinsDeployerBase {
|
|
14
26
|
ZoraFactoryImpl public factoryProxy;
|
|
15
27
|
|
|
16
28
|
function test_canUpgradeFromVersionWithoutContractName() public {
|
|
@@ -19,7 +31,7 @@ contract UpgradesTest is Test {
|
|
|
19
31
|
|
|
20
32
|
factoryProxy = ZoraFactoryImpl(0x777777751622c0d3258f214F9DF38E35BF45baF3);
|
|
21
33
|
|
|
22
|
-
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(factoryProxy.
|
|
34
|
+
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(factoryProxy.coinImpl(), address(coinV4Impl));
|
|
23
35
|
|
|
24
36
|
vm.prank(factoryProxy.owner());
|
|
25
37
|
factoryProxy.upgradeToAndCall(address(newImpl), "");
|
|
@@ -34,7 +46,7 @@ contract UpgradesTest is Test {
|
|
|
34
46
|
|
|
35
47
|
factoryProxy = ZoraFactoryImpl(0x777777751622c0d3258f214F9DF38E35BF45baF3);
|
|
36
48
|
|
|
37
|
-
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(factoryProxy.
|
|
49
|
+
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(factoryProxy.coinImpl(), address(coinV4Impl));
|
|
38
50
|
|
|
39
51
|
vm.prank(factoryProxy.owner());
|
|
40
52
|
factoryProxy.upgradeToAndCall(address(newImpl), "");
|
|
@@ -52,16 +64,96 @@ contract UpgradesTest is Test {
|
|
|
52
64
|
|
|
53
65
|
factoryProxy = ZoraFactoryImpl(0x777777751622c0d3258f214F9DF38E35BF45baF3);
|
|
54
66
|
|
|
55
|
-
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(factoryProxy.
|
|
67
|
+
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(factoryProxy.coinImpl(), address(coinV4Impl));
|
|
56
68
|
|
|
57
69
|
vm.prank(factoryProxy.owner());
|
|
58
70
|
factoryProxy.upgradeToAndCall(address(newImpl), "");
|
|
59
71
|
|
|
60
|
-
ZoraFactoryImpl newImpl2 = new ZoraFactoryImpl(factoryProxy.
|
|
72
|
+
ZoraFactoryImpl newImpl2 = new ZoraFactoryImpl(factoryProxy.coinImpl(), factoryProxy.coinV4Impl());
|
|
61
73
|
|
|
62
74
|
vm.prank(factoryProxy.owner());
|
|
63
75
|
factoryProxy.upgradeToAndCall(address(newImpl2), "");
|
|
64
76
|
|
|
65
77
|
assertEq(factoryProxy.implementation(), address(newImpl2));
|
|
66
78
|
}
|
|
79
|
+
|
|
80
|
+
function test_canUpgradeAndSwap() public {
|
|
81
|
+
vm.createSelectFork("base");
|
|
82
|
+
|
|
83
|
+
factoryProxy = ZoraFactoryImpl(0x777777751622c0d3258f214F9DF38E35BF45baF3);
|
|
84
|
+
|
|
85
|
+
CoinsDeployment memory deployment = readDeployment();
|
|
86
|
+
|
|
87
|
+
vm.prank(factoryProxy.owner());
|
|
88
|
+
factoryProxy.upgradeToAndCall(deployment.zoraFactoryImpl, "");
|
|
89
|
+
|
|
90
|
+
// deploy a v4 coin
|
|
91
|
+
|
|
92
|
+
bytes memory poolConfig = CoinConfigurationVersions.defaultDopplerMultiCurveUniV4(ZORA);
|
|
93
|
+
|
|
94
|
+
uint128 amountIn = 1 ether;
|
|
95
|
+
|
|
96
|
+
address buySupplyWithSwapRouterHook = deployment.buySupplyWithSwapRouterHook;
|
|
97
|
+
|
|
98
|
+
// build weth to usdc swap
|
|
99
|
+
bytes memory call = abi.encodeWithSelector(
|
|
100
|
+
ISwapRouter.exactInputSingle.selector,
|
|
101
|
+
ISwapRouter.ExactInputSingleParams({
|
|
102
|
+
tokenIn: WETH_ADDRESS,
|
|
103
|
+
tokenOut: ZORA,
|
|
104
|
+
fee: 3000,
|
|
105
|
+
recipient: buySupplyWithSwapRouterHook,
|
|
106
|
+
amountIn: amountIn,
|
|
107
|
+
amountOutMinimum: 0,
|
|
108
|
+
sqrtPriceLimitX96: 0
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
address buyRecipient = makeAddr("buyRecipient");
|
|
113
|
+
|
|
114
|
+
address trader = 0xC077e4cC02fa01A5b7fAca1acE9BBe9f5ac5Af9F;
|
|
115
|
+
|
|
116
|
+
vm.startPrank(trader);
|
|
117
|
+
vm.deal(trader, amountIn);
|
|
118
|
+
|
|
119
|
+
(address coinAddress, ) = factoryProxy.deploy{value: amountIn}(
|
|
120
|
+
users.creator,
|
|
121
|
+
_getDefaultOwners(),
|
|
122
|
+
"https://test.com",
|
|
123
|
+
"Testcoin",
|
|
124
|
+
"TEST",
|
|
125
|
+
poolConfig,
|
|
126
|
+
users.platformReferrer,
|
|
127
|
+
buySupplyWithSwapRouterHook,
|
|
128
|
+
abi.encode(buyRecipient, call),
|
|
129
|
+
keccak256("test")
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// do some swaps to test out
|
|
133
|
+
_swapSomeCurrencyForCoin(ICoinV4(coinAddress), ZORA, uint128(IERC20(ZORA).balanceOf(trader)), trader);
|
|
134
|
+
|
|
135
|
+
// do some swaps to test out
|
|
136
|
+
_swapSomeCoinForCurrency(ICoinV4(coinAddress), ZORA, uint128(IERC20(coinAddress).balanceOf(trader)), trader);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function test_realSwapUsingCurrentCode() external {
|
|
140
|
+
bytes[] memory inputs = new bytes[](5);
|
|
141
|
+
|
|
142
|
+
vm.createSelectFork("base", 31138268);
|
|
143
|
+
|
|
144
|
+
address trader = vm.parseAddress("0xa3c881f39972925d865b300bcd65e72a6222c10a");
|
|
145
|
+
|
|
146
|
+
ICoinV4 coin = ICoinV4(vm.parseAddress("0xca1de5b8e8336326d5749fde43e245285cd1daf1"));
|
|
147
|
+
|
|
148
|
+
PoolKey memory key = coin.getPoolKey();
|
|
149
|
+
|
|
150
|
+
address[] memory trustedMessageSenders = new address[](0);
|
|
151
|
+
deployCodeTo(
|
|
152
|
+
"ZoraV4CoinHook.sol:ZoraV4CoinHook",
|
|
153
|
+
abi.encode(V4_POOL_MANAGER, 0x3d7A3f3351855e135CF89AB412A7C2AA449f9296, trustedMessageSenders),
|
|
154
|
+
address(coin.hooks())
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
_swapSomeCurrencyForCoin(coin, ZORA, uint128(IERC20(ZORA).balanceOf(trader)), trader);
|
|
158
|
+
}
|
|
67
159
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
5
|
+
|
|
6
|
+
contract MockERC20 is ERC20 {
|
|
7
|
+
constructor(string memory name, string memory symbol) ERC20(name, symbol) {}
|
|
8
|
+
|
|
9
|
+
function mint(address to, uint256 amount) external {
|
|
10
|
+
_mint(to, amount);
|
|
11
|
+
}
|
|
12
|
+
}
|