@zoralabs/coins 1.1.0 → 1.1.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 +97 -95
- package/CHANGELOG.md +8 -0
- package/abis/BaseCoin.json +6 -1
- package/abis/BaseZoraV4CoinHook.json +119 -0
- package/abis/Coin.json +6 -1
- package/abis/CoinTest.json +14 -0
- package/abis/CoinV4.json +6 -1
- package/abis/ContentCoinHook.json +119 -0
- package/abis/CreatorCoin.json +6 -1
- package/abis/CreatorCoinHook.json +119 -0
- package/abis/ERC165.json +21 -0
- package/abis/ERC165Upgradeable.json +44 -0
- package/abis/FeeEstimatorHook.json +119 -0
- package/abis/ICoin.json +5 -0
- package/abis/ICoinV3.json +5 -0
- package/abis/ICoinV4.json +5 -0
- package/abis/ICreatorCoin.json +5 -0
- package/abis/LiquidityMigrationTest.json +7 -0
- package/abis/UpgradeHooks.json +35 -0
- package/abis/UpgradesTest.json +21 -0
- package/addresses/8453.json +11 -7
- package/dist/index.cjs +6 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/wagmiGenerated.d.ts +15 -3
- package/dist/wagmiGenerated.d.ts.map +1 -1
- package/package/wagmiGenerated.ts +6 -3
- package/package.json +1 -1
- package/script/DeployUpgradeGate.s.sol +1 -1
- package/script/PrintRegisterUpgradePath.s.sol +35 -0
- package/script/UpgradeCoinImpl.sol +1 -1
- package/script/UpgradeHooks.s.sol +23 -0
- package/src/BaseCoin.sol +25 -8
- package/src/CoinV4.sol +2 -2
- package/src/deployment/CoinsDeployerBase.sol +29 -9
- package/src/hooks/BaseZoraV4CoinHook.sol +117 -3
- package/src/interfaces/ICoin.sol +3 -0
- package/src/libs/CoinRewardsV4.sol +18 -4
- package/src/libs/HooksDeployment.sol +13 -0
- package/src/libs/V4Liquidity.sol +27 -0
- package/src/version/ContractVersionBase.sol +1 -1
- package/test/Coin.t.sol +23 -0
- package/test/LiquidityMigration.t.sol +27 -0
- package/test/Upgrades.t.sol +180 -1
- package/test/utils/BaseTest.sol +5 -1
- /package/script/{DeployHooks.s.sol → DeployPostDeploymentHooks.s.sol} +0 -0
package/src/libs/V4Liquidity.sol
CHANGED
|
@@ -48,6 +48,9 @@ library V4Liquidity {
|
|
|
48
48
|
error InvalidCallbackId(uint8 callbackId);
|
|
49
49
|
|
|
50
50
|
/// @notice Locks the pool, and mint initial positions to the hook
|
|
51
|
+
/// @param poolManager The pool manager.
|
|
52
|
+
/// @param poolKey The pool key.
|
|
53
|
+
/// @param positions The positions.
|
|
51
54
|
function lockAndMint(IPoolManager poolManager, PoolKey memory poolKey, LpPosition[] memory positions) internal {
|
|
52
55
|
bytes memory data = abi.encode(MINT_CALLBACK_ID, abi.encode(MintCallbackData({poolKey: poolKey, positions: positions})));
|
|
53
56
|
|
|
@@ -129,11 +132,35 @@ library V4Liquidity {
|
|
|
129
132
|
return abi.encode(result);
|
|
130
133
|
}
|
|
131
134
|
|
|
135
|
+
function generatePositionsFromMigratedLiquidity(
|
|
136
|
+
uint160 sqrtPriceX96,
|
|
137
|
+
BurnedPosition[] calldata migratedLiquidity
|
|
138
|
+
) internal pure returns (LpPosition[] memory positions) {
|
|
139
|
+
positions = new LpPosition[](migratedLiquidity.length);
|
|
140
|
+
|
|
141
|
+
for (uint256 i = 0; i < migratedLiquidity.length; i++) {
|
|
142
|
+
uint128 liquidity = LiquidityAmounts.getLiquidityForAmounts(
|
|
143
|
+
sqrtPriceX96,
|
|
144
|
+
TickMath.getSqrtPriceAtTick(migratedLiquidity[i].tickLower),
|
|
145
|
+
TickMath.getSqrtPriceAtTick(migratedLiquidity[i].tickUpper),
|
|
146
|
+
migratedLiquidity[i].amount0Received,
|
|
147
|
+
migratedLiquidity[i].amount1Received
|
|
148
|
+
);
|
|
149
|
+
positions[i] = LpPosition({liquidity: liquidity, tickLower: migratedLiquidity[i].tickLower, tickUpper: migratedLiquidity[i].tickUpper});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
132
153
|
function collectFees(IPoolManager poolManager, PoolKey memory poolKey, LpPosition[] storage positions) internal returns (int128 balance0, int128 balance1) {
|
|
133
154
|
ModifyLiquidityParams memory params;
|
|
134
155
|
uint256 numPositions = positions.length;
|
|
135
156
|
|
|
136
157
|
for (uint256 i; i < numPositions; i++) {
|
|
158
|
+
// if there is no liquidity, skip
|
|
159
|
+
uint128 liquidity = getLiquidity(poolManager, address(this), poolKey, positions[i].tickLower, positions[i].tickUpper);
|
|
160
|
+
if (liquidity == 0) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
137
164
|
params = ModifyLiquidityParams({
|
|
138
165
|
tickLower: positions[i].tickLower,
|
|
139
166
|
tickUpper: positions[i].tickUpper,
|
|
@@ -9,6 +9,6 @@ import {IVersionedContract} from "@zoralabs/shared-contracts/interfaces/IVersion
|
|
|
9
9
|
contract ContractVersionBase is IVersionedContract {
|
|
10
10
|
/// @notice The version of the contract
|
|
11
11
|
function contractVersion() external pure override returns (string memory) {
|
|
12
|
-
return "1.1.
|
|
12
|
+
return "1.1.1";
|
|
13
13
|
}
|
|
14
14
|
}
|
package/test/Coin.t.sol
CHANGED
|
@@ -8,6 +8,8 @@ import {CoinConstants} from "../src/libs/CoinConstants.sol";
|
|
|
8
8
|
import {IZoraFactory} from "../src/interfaces/IZoraFactory.sol";
|
|
9
9
|
import {IHasRewardsRecipients} from "../src/interfaces/IHasRewardsRecipients.sol";
|
|
10
10
|
import {PoolConfiguration} from "../src/interfaces/ICoin.sol";
|
|
11
|
+
import {IERC165, IERC7572, ICoin, ICoinComments, IERC20} from "../src/BaseCoin.sol";
|
|
12
|
+
import {IERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
|
|
11
13
|
|
|
12
14
|
contract CoinTest is BaseTest {
|
|
13
15
|
using stdJson for string;
|
|
@@ -16,6 +18,17 @@ contract CoinTest is BaseTest {
|
|
|
16
18
|
super.setUp();
|
|
17
19
|
}
|
|
18
20
|
|
|
21
|
+
function test_contract_ierc165_support() public {
|
|
22
|
+
_deployCoin();
|
|
23
|
+
assertEq(coin.supportsInterface(type(IZoraFactory).interfaceId), false);
|
|
24
|
+
assertEq(coin.supportsInterface(bytes4(0x00000000)), false);
|
|
25
|
+
assertEq(coin.supportsInterface(type(IERC165).interfaceId), true);
|
|
26
|
+
assertEq(coin.supportsInterface(type(IERC7572).interfaceId), true);
|
|
27
|
+
assertEq(coin.supportsInterface(type(ICoin).interfaceId), true);
|
|
28
|
+
assertEq(coin.supportsInterface(type(ICoinComments).interfaceId), true);
|
|
29
|
+
assertEq(coin.supportsInterface(type(IERC7572).interfaceId), true);
|
|
30
|
+
}
|
|
31
|
+
|
|
19
32
|
function test_contract_version() public {
|
|
20
33
|
_deployCoin();
|
|
21
34
|
string memory package = vm.readFile("./package.json");
|
|
@@ -658,4 +671,14 @@ contract CoinTest is BaseTest {
|
|
|
658
671
|
vm.expectRevert(abi.encodeWithSelector(MultiOwnable.OnlyOwner.selector));
|
|
659
672
|
coin.setNameAndSymbol(newName, newSymbol);
|
|
660
673
|
}
|
|
674
|
+
|
|
675
|
+
function test_update_metadata_reverts_if_name_is_blank() public {
|
|
676
|
+
_deployCoin();
|
|
677
|
+
string memory newName = "";
|
|
678
|
+
string memory newSymbol = "NEW";
|
|
679
|
+
|
|
680
|
+
vm.prank(users.creator);
|
|
681
|
+
vm.expectRevert(abi.encodeWithSelector(ICoin.NameIsRequired.selector));
|
|
682
|
+
coin.setNameAndSymbol(newName, newSymbol);
|
|
683
|
+
}
|
|
661
684
|
}
|
|
@@ -123,6 +123,33 @@ contract LiquidityMigrationTest is BaseTest {
|
|
|
123
123
|
assertEq(newPoolKey.tickSpacing, poolKey.tickSpacing, "poolkey tickSpacing");
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
function test_migrateLiquidity_enablesSwapsOnOldPoolKey() public {
|
|
127
|
+
address currency = address(mockERC20A);
|
|
128
|
+
mockERC20A.mint(address(poolManager), 1_000_000_000 ether);
|
|
129
|
+
_deployV4Coin(currency);
|
|
130
|
+
|
|
131
|
+
address trader = makeAddr("trader");
|
|
132
|
+
|
|
133
|
+
mockERC20A.mint(trader, 10 ether);
|
|
134
|
+
|
|
135
|
+
// do some swaps
|
|
136
|
+
_swapSomeCurrencyForCoin(coinV4, currency, 1 ether, trader);
|
|
137
|
+
_swapSomeCoinForCurrency(coinV4, currency, uint128(coinV4.balanceOf(trader)), trader);
|
|
138
|
+
|
|
139
|
+
address newHook = address(new LiquidityMigrationReceiver());
|
|
140
|
+
|
|
141
|
+
PoolKey memory poolKey = coinV4.getPoolKey();
|
|
142
|
+
|
|
143
|
+
registerUpgradePath(address(poolKey.hooks), address(newHook));
|
|
144
|
+
|
|
145
|
+
// migrate the liquidity
|
|
146
|
+
vm.prank(users.creator);
|
|
147
|
+
coinV4.migrateLiquidity(address(newHook), "");
|
|
148
|
+
|
|
149
|
+
// now swap using the existing pool key, it should succeed
|
|
150
|
+
_swapSomeCurrencyForCoin(poolKey, coinV4, currency, uint128(mockERC20A.balanceOf(trader)), trader);
|
|
151
|
+
}
|
|
152
|
+
|
|
126
153
|
function test_migrateLiquidity_emitsLiquidityMigrated() public {
|
|
127
154
|
address currency = address(mockERC20A);
|
|
128
155
|
_deployV4Coin(currency);
|
package/test/Upgrades.t.sol
CHANGED
|
@@ -13,8 +13,20 @@ import {IWETH} from "../src/interfaces/IWETH.sol";
|
|
|
13
13
|
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
|
|
14
14
|
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
|
|
15
15
|
import {BuySupplyWithSwapRouterHook} from "../src/hooks/deployment/BuySupplyWithSwapRouterHook.sol";
|
|
16
|
-
|
|
16
|
+
import {ContentCoinHook} from "../src/hooks/ContentCoinHook.sol";
|
|
17
17
|
import {console} from "forge-std/console.sol";
|
|
18
|
+
import {IDeployedCoinVersionLookup} from "../src/interfaces/IDeployedCoinVersionLookup.sol";
|
|
19
|
+
import {IHooksUpgradeGate} from "../src/interfaces/IHooksUpgradeGate.sol";
|
|
20
|
+
import {HooksDeployment} from "../src/libs/HooksDeployment.sol";
|
|
21
|
+
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
|
|
22
|
+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
|
23
|
+
import {MultiOwnable} from "../src/utils/MultiOwnable.sol";
|
|
24
|
+
import {CoinV4} from "../src/CoinV4.sol";
|
|
25
|
+
import {UniV4SwapHelper} from "../src/libs/UniV4SwapHelper.sol";
|
|
26
|
+
import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
|
|
27
|
+
import {IZoraV4CoinHook} from "../src/interfaces/IZoraV4CoinHook.sol";
|
|
28
|
+
import {PoolStateReader} from "../src/libs/PoolStateReader.sol";
|
|
29
|
+
import {LpPosition} from "../src/types/LpPosition.sol";
|
|
18
30
|
|
|
19
31
|
contract BadImpl {
|
|
20
32
|
function contractName() public pure returns (string memory) {
|
|
@@ -159,4 +171,171 @@ contract UpgradesTest is BaseTest, CoinsDeployerBase {
|
|
|
159
171
|
// do some swaps to test out
|
|
160
172
|
_swapSomeCoinForCurrency(ICoinV4(coinAddress), ZORA, uint128(IERC20(coinAddress).balanceOf(trader)), trader);
|
|
161
173
|
}
|
|
174
|
+
|
|
175
|
+
address coinVersionLookup = 0x777777751622c0d3258f214F9DF38E35BF45baF3;
|
|
176
|
+
address upgradeGate = 0xD88f6BdD765313CaFA5888C177c325E2C3AbF2D2;
|
|
177
|
+
|
|
178
|
+
function _swapSomeCurrencyForCoinAndExpectRevert(ICoinV4 _coin, address currency, uint128 amountIn, address trader) internal {
|
|
179
|
+
uint128 minAmountOut = uint128(0);
|
|
180
|
+
|
|
181
|
+
(bytes memory commands, bytes[] memory inputs) = UniV4SwapHelper.buildExactInputSingleSwapCommand(
|
|
182
|
+
currency,
|
|
183
|
+
amountIn,
|
|
184
|
+
address(_coin),
|
|
185
|
+
minAmountOut,
|
|
186
|
+
_coin.getPoolKey(),
|
|
187
|
+
bytes("")
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
vm.startPrank(trader);
|
|
191
|
+
UniV4SwapHelper.approveTokenWithPermit2(permit2, address(router), currency, amountIn, uint48(block.timestamp + 1 days));
|
|
192
|
+
|
|
193
|
+
// Execute the swap
|
|
194
|
+
uint256 deadline = block.timestamp + 20;
|
|
195
|
+
vm.expectRevert();
|
|
196
|
+
router.execute(commands, inputs, deadline);
|
|
197
|
+
|
|
198
|
+
vm.stopPrank();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function test_canCanFixBrokenContentCoinAndSwap() public {
|
|
202
|
+
vm.createSelectFork("base", 31835069);
|
|
203
|
+
|
|
204
|
+
address trader = 0xf69fEc6d858c77e969509843852178bd24CAd2B6;
|
|
205
|
+
|
|
206
|
+
address contentCoin = 0x4E93A01c90f812284F71291a8d1415a904957156;
|
|
207
|
+
|
|
208
|
+
address creatorCoin = ICoinV4(contentCoin).currency();
|
|
209
|
+
|
|
210
|
+
uint256 amountIn = IERC20(creatorCoin).balanceOf(trader);
|
|
211
|
+
|
|
212
|
+
require(amountIn > 0, "no balance");
|
|
213
|
+
|
|
214
|
+
// this swap should revert because the content coin is broken
|
|
215
|
+
_swapSomeCurrencyForCoinAndExpectRevert(ICoinV4(contentCoin), creatorCoin, uint128(amountIn), trader);
|
|
216
|
+
|
|
217
|
+
bytes memory creationCode = HooksDeployment.contentCoinCreationCode(address(poolManager), coinVersionLookup, new address[](0), upgradeGate);
|
|
218
|
+
|
|
219
|
+
(IHooks newHook, ) = HooksDeployment.deployHookWithExistingOrNewSalt(address(this), creationCode, bytes32(0));
|
|
220
|
+
|
|
221
|
+
// etch new hook into the content coin, it shouldn't revert anymore when swapping
|
|
222
|
+
vm.etch(address(ICoinV4(contentCoin).hooks()), address(newHook).code);
|
|
223
|
+
|
|
224
|
+
_swapSomeCurrencyForCoin(ICoinV4(contentCoin), creatorCoin, uint128(amountIn), trader);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function test_canUpgradeBrokenContentCoinAndSwap() public {
|
|
228
|
+
vm.createSelectFork("base", 31835069);
|
|
229
|
+
|
|
230
|
+
address trader = 0xf69fEc6d858c77e969509843852178bd24CAd2B6;
|
|
231
|
+
|
|
232
|
+
address contentCoin = 0x4E93A01c90f812284F71291a8d1415a904957156;
|
|
233
|
+
|
|
234
|
+
address creatorCoin = ICoinV4(contentCoin).currency();
|
|
235
|
+
|
|
236
|
+
address existingHook = 0xd3D133469ADC85e01A4887404D8AC12d630e9040;
|
|
237
|
+
|
|
238
|
+
uint256 amountIn = IERC20(creatorCoin).balanceOf(trader);
|
|
239
|
+
|
|
240
|
+
bytes memory creationCode = HooksDeployment.contentCoinCreationCode(address(poolManager), coinVersionLookup, new address[](0), upgradeGate);
|
|
241
|
+
|
|
242
|
+
(IHooks newHook, ) = HooksDeployment.deployHookWithExistingOrNewSalt(address(this), creationCode, bytes32(0));
|
|
243
|
+
|
|
244
|
+
address[] memory baseImpls = new address[](1);
|
|
245
|
+
baseImpls[0] = existingHook;
|
|
246
|
+
|
|
247
|
+
vm.prank(Ownable(upgradeGate).owner());
|
|
248
|
+
IHooksUpgradeGate(upgradeGate).registerUpgradePath(baseImpls, address(newHook));
|
|
249
|
+
|
|
250
|
+
vm.prank(MultiOwnable(contentCoin).owners()[0]);
|
|
251
|
+
CoinV4(contentCoin).migrateLiquidity(address(newHook), "");
|
|
252
|
+
|
|
253
|
+
// do some swaps to test out
|
|
254
|
+
_swapSomeCurrencyForCoin(ICoinV4(contentCoin), creatorCoin, uint128(amountIn), trader);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function getPositionInfo(
|
|
258
|
+
PoolKey memory key,
|
|
259
|
+
address owner,
|
|
260
|
+
int24 tickLower,
|
|
261
|
+
int24 tickUpper
|
|
262
|
+
) internal view returns (uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128) {
|
|
263
|
+
return StateLibrary.getPositionInfo(poolManager, key.toId(), owner, tickLower, tickUpper, bytes32(0));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function getLiquidityForPositions(PoolKey memory key, LpPosition[] memory positions) internal view returns (uint128[] memory liquidityForPositions) {
|
|
267
|
+
liquidityForPositions = new uint128[](positions.length);
|
|
268
|
+
|
|
269
|
+
for (uint256 i = 0; i < positions.length; i++) {
|
|
270
|
+
(uint128 liquidity, , ) = getPositionInfo(key, address(key.hooks), positions[i].tickLower, positions[i].tickUpper);
|
|
271
|
+
liquidityForPositions[i] = liquidity;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function getLiquidityForPoolCoin(ICoinV4 coin) internal view returns (uint128[] memory liquidityForPositions) {
|
|
276
|
+
return getLiquidityForPositions(coin.getPoolKey(), IZoraV4CoinHook(address(coin.hooks())).getPoolCoin(coin.getPoolKey()).positions);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function test_canUpgradeBrokenCreatorCoinAndSwap() public {
|
|
280
|
+
vm.createSelectFork("base", 31872861);
|
|
281
|
+
|
|
282
|
+
address trader = 0xf69fEc6d858c77e969509843852178bd24CAd2B6;
|
|
283
|
+
|
|
284
|
+
ICoinV4 creatorCoin = ICoinV4(0x2F03aB8fD97F5874bc3274C296Bb954Ae92EdA34);
|
|
285
|
+
|
|
286
|
+
address zora = creatorCoin.currency();
|
|
287
|
+
|
|
288
|
+
address existingHook = address(creatorCoin.hooks());
|
|
289
|
+
|
|
290
|
+
bytes memory creationCode = HooksDeployment.creatorCoinCreationCode(address(poolManager), coinVersionLookup, new address[](0), upgradeGate);
|
|
291
|
+
|
|
292
|
+
(IHooks newHook, ) = HooksDeployment.deployHookWithExistingOrNewSalt(address(this), creationCode, bytes32(0));
|
|
293
|
+
|
|
294
|
+
address[] memory baseImpls = new address[](1);
|
|
295
|
+
baseImpls[0] = existingHook;
|
|
296
|
+
|
|
297
|
+
vm.prank(Ownable(upgradeGate).owner());
|
|
298
|
+
IHooksUpgradeGate(upgradeGate).registerUpgradePath(baseImpls, address(newHook));
|
|
299
|
+
|
|
300
|
+
LpPosition[] memory beforePositions = IZoraV4CoinHook(address(creatorCoin.hooks())).getPoolCoin(creatorCoin.getPoolKey()).positions;
|
|
301
|
+
PoolKey memory beforeKey = creatorCoin.getPoolKey();
|
|
302
|
+
|
|
303
|
+
uint128[] memory beforeLiquidity = getLiquidityForPositions(beforeKey, beforePositions);
|
|
304
|
+
// get before price
|
|
305
|
+
uint160 beforePrice = PoolStateReader.getSqrtPriceX96(creatorCoin.getPoolKey(), poolManager);
|
|
306
|
+
|
|
307
|
+
vm.prank(MultiOwnable(address(creatorCoin)).owners()[0]);
|
|
308
|
+
CoinV4(address(creatorCoin)).migrateLiquidity(address(newHook), "");
|
|
309
|
+
|
|
310
|
+
// get liquidity of original positions after migration
|
|
311
|
+
uint128[] memory liquidityOfPositionsAfterMigration = getLiquidityForPositions(beforeKey, beforePositions);
|
|
312
|
+
|
|
313
|
+
// there should be no liquidity left in the original positions after migration
|
|
314
|
+
for (uint256 i = 0; i < liquidityOfPositionsAfterMigration.length; i++) {
|
|
315
|
+
assertEq(liquidityOfPositionsAfterMigration[i], 0);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// get liquidity of new positions after migration
|
|
319
|
+
PoolKey memory afterKey = creatorCoin.getPoolKey();
|
|
320
|
+
LpPosition[] memory afterPositions = IZoraV4CoinHook(address(afterKey.hooks)).getPoolCoin(afterKey).positions;
|
|
321
|
+
uint128[] memory afterLiquidity = getLiquidityForPositions(afterKey, afterPositions);
|
|
322
|
+
|
|
323
|
+
for (uint256 i = 0; i < beforeLiquidity.length; i++) {
|
|
324
|
+
// we added any extra liquidity to the last position, so we don't expect it to be the same
|
|
325
|
+
if (i != beforeLiquidity.length - 1) {
|
|
326
|
+
assertApproxEqAbs(beforeLiquidity[i], afterLiquidity[i], 200);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
uint160 afterPrice = PoolStateReader.getSqrtPriceX96(creatorCoin.getPoolKey(), poolManager);
|
|
331
|
+
|
|
332
|
+
assertEq(beforePrice, afterPrice);
|
|
333
|
+
|
|
334
|
+
// make sure that the new hook has no balance of 0 or 1
|
|
335
|
+
assertApproxEqAbs(creatorCoin.getPoolKey().currency0.balanceOf(address(newHook)), 0, 10);
|
|
336
|
+
assertApproxEqAbs(creatorCoin.getPoolKey().currency1.balanceOf(address(newHook)), 0, 10);
|
|
337
|
+
|
|
338
|
+
// now try to swap some currency for the creator coin - it should succeed
|
|
339
|
+
_swapSomeCurrencyForCoin(creatorCoin, zora, uint128(IERC20(zora).balanceOf(trader) / 2), trader);
|
|
340
|
+
}
|
|
162
341
|
}
|
package/test/utils/BaseTest.sol
CHANGED
|
@@ -190,6 +190,10 @@ contract BaseTest is Test, ContractAddresses {
|
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
function _swapSomeCurrencyForCoin(ICoinV4 _coin, address currency, uint128 amountIn, address trader) internal {
|
|
193
|
+
_swapSomeCurrencyForCoin(_coin.getPoolKey(), _coin, currency, amountIn, trader);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function _swapSomeCurrencyForCoin(PoolKey memory poolKey, ICoinV4 _coin, address currency, uint128 amountIn, address trader) internal {
|
|
193
197
|
uint128 minAmountOut = uint128(0);
|
|
194
198
|
|
|
195
199
|
(bytes memory commands, bytes[] memory inputs) = UniV4SwapHelper.buildExactInputSingleSwapCommand(
|
|
@@ -197,7 +201,7 @@ contract BaseTest is Test, ContractAddresses {
|
|
|
197
201
|
amountIn,
|
|
198
202
|
address(_coin),
|
|
199
203
|
minAmountOut,
|
|
200
|
-
|
|
204
|
+
poolKey,
|
|
201
205
|
bytes("")
|
|
202
206
|
);
|
|
203
207
|
|
|
File without changes
|