@zoralabs/coins 0.9.0 → 1.0.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.
Files changed (124) hide show
  1. package/.turbo/turbo-build.log +131 -114
  2. package/CHANGELOG.md +40 -0
  3. package/abis/BaseCoin.json +26 -118
  4. package/abis/BaseTest.json +47 -0
  5. package/abis/Coin.json +171 -63
  6. package/abis/CoinDopplerMultiCurve.json +38 -0
  7. package/abis/CoinRewardsV4.json +54 -0
  8. package/abis/CoinTest.json +53 -20
  9. package/abis/CoinUniV4Test.json +1053 -0
  10. package/abis/CoinV4.json +234 -211
  11. package/abis/DeployScript.json +47 -0
  12. package/abis/DeployedCoinVersionLookup.json +21 -0
  13. package/abis/DeployedCoinVersionLookupTest.json +716 -0
  14. package/abis/DifferentNamespaceVersionLookup.json +39 -0
  15. package/abis/DopplerUniswapV3Test.json +49 -93
  16. package/abis/ERC20.json +310 -0
  17. package/abis/FactoryTest.json +85 -7
  18. package/abis/FeeEstimatorHook.json +1528 -0
  19. package/abis/HooksDeployment.json +23 -0
  20. package/abis/HooksTest.json +47 -0
  21. package/abis/ICoin.json +40 -71
  22. package/abis/ICoinV3.json +879 -0
  23. package/abis/ICoinV4.json +915 -0
  24. package/abis/IDeployedCoinVersionLookup.json +21 -0
  25. package/abis/IERC721.json +36 -36
  26. package/abis/IHasPoolKey.json +42 -0
  27. package/abis/IHasRewardsRecipients.json +54 -0
  28. package/abis/IHasSwapPath.json +60 -0
  29. package/abis/IMsgSender.json +15 -0
  30. package/abis/IPoolConfigEncoding.json +46 -0
  31. package/abis/ISwapPathRouter.json +92 -0
  32. package/abis/IUniversalRouter.json +61 -0
  33. package/abis/IUnlockCallback.json +21 -0
  34. package/abis/IV4Quoter.json +310 -0
  35. package/abis/IZoraFactory.json +191 -11
  36. package/abis/IZoraV4CoinHook.json +348 -4
  37. package/abis/MockERC20.json +21 -0
  38. package/abis/MultiOwnableTest.json +47 -0
  39. package/abis/{CoinConfigurationVersions.json → Position.json} +1 -1
  40. package/abis/PrintUpgradeCommand.json +9 -0
  41. package/abis/ProxyShim.json +24 -0
  42. package/abis/StateLibrary.json +80 -0
  43. package/abis/TestDeployedCoinVersionLookupImplementation.json +39 -0
  44. package/abis/TestV4Swap.json +9 -0
  45. package/abis/UpgradeCoinImpl.json +47 -0
  46. package/abis/UpgradesTest.json +67 -0
  47. package/abis/Vm.json +1482 -111
  48. package/abis/VmSafe.json +856 -32
  49. package/abis/ZoraFactoryImpl.json +339 -1
  50. package/abis/ZoraV4CoinHook.json +455 -5
  51. package/addresses/8453.json +8 -4
  52. package/addresses/84532.json +8 -4
  53. package/dist/index.cjs +1920 -169
  54. package/dist/index.cjs.map +1 -1
  55. package/dist/index.js +1916 -169
  56. package/dist/index.js.map +1 -1
  57. package/dist/wagmiGenerated.d.ts +2599 -183
  58. package/dist/wagmiGenerated.d.ts.map +1 -1
  59. package/package/wagmiGenerated.ts +1928 -165
  60. package/package.json +8 -3
  61. package/remappings.txt +6 -1
  62. package/script/CoinsDeployerBase.sol +74 -11
  63. package/script/DeployDevFactory.s.sol +21 -0
  64. package/script/PrintUpgradeCommand.s.sol +13 -0
  65. package/script/Simulate.s.sol +1 -10
  66. package/script/TestBackingCoinSwap.s.sol +146 -0
  67. package/script/TestV4Swap.s.sol +136 -0
  68. package/script/UpgradeFactoryImpl.s.sol +1 -1
  69. package/src/BaseCoin.sol +176 -0
  70. package/src/Coin.sol +87 -202
  71. package/src/CoinV4.sol +121 -0
  72. package/src/ZoraFactoryImpl.sol +208 -36
  73. package/src/hooks/ZoraV4CoinHook.sol +195 -0
  74. package/src/hooks/{BaseCoinDeployHook.sol → deployment/BaseCoinDeployHook.sol} +3 -3
  75. package/src/hooks/{BuySupplyWithSwapRouterHook.sol → deployment/BuySupplyWithSwapRouterHook.sol} +7 -5
  76. package/src/interfaces/ICoin.sol +31 -39
  77. package/src/interfaces/ICoinV3.sol +71 -0
  78. package/src/interfaces/ICoinV4.sol +69 -0
  79. package/src/interfaces/IDeployedCoinVersionLookup.sol +11 -0
  80. package/src/interfaces/IMsgSender.sol +9 -0
  81. package/src/interfaces/IPoolConfigEncoding.sol +14 -0
  82. package/src/interfaces/ISwapPathRouter.sol +14 -0
  83. package/src/interfaces/IZoraFactory.sol +65 -27
  84. package/src/interfaces/IZoraV4CoinHook.sol +116 -0
  85. package/src/libs/CoinCommon.sol +15 -0
  86. package/src/libs/CoinConfigurationVersions.sol +116 -1
  87. package/src/libs/CoinConstants.sol +5 -0
  88. package/src/libs/CoinDopplerMultiCurve.sol +134 -0
  89. package/src/libs/CoinDopplerUniV3.sol +19 -171
  90. package/src/libs/CoinRewards.sol +195 -0
  91. package/src/libs/CoinRewardsV4.sol +180 -0
  92. package/src/libs/CoinSetup.sol +57 -0
  93. package/src/libs/CoinSetupV3.sol +6 -67
  94. package/src/libs/DopplerMath.sol +156 -0
  95. package/src/libs/HooksDeployment.sol +84 -0
  96. package/src/libs/MarketConstants.sol +4 -0
  97. package/src/libs/PoolStateReader.sol +22 -0
  98. package/src/libs/UniV3BuySell.sol +74 -292
  99. package/src/libs/UniV4SwapHelper.sol +65 -0
  100. package/src/libs/UniV4SwapToCurrency.sol +109 -0
  101. package/src/libs/V4Liquidity.sol +129 -0
  102. package/src/types/PoolConfiguration.sol +15 -0
  103. package/src/utils/DeployedCoinVersionLookup.sol +52 -0
  104. package/src/version/ContractVersionBase.sol +1 -1
  105. package/test/Coin.t.sol +78 -88
  106. package/test/CoinDopplerUniV3.t.sol +32 -171
  107. package/test/CoinUniV4.t.sol +752 -0
  108. package/test/{Hooks.t.sol → DeploymentHooks.t.sol} +2 -6
  109. package/test/Factory.t.sol +80 -47
  110. package/test/MultiOwnable.t.sol +6 -3
  111. package/test/Upgrades.t.sol +6 -5
  112. package/test/mocks/MockERC20.sol +12 -0
  113. package/test/utils/BaseTest.sol +106 -56
  114. package/test/utils/DeployedCoinVersionLookup.t.sol +127 -0
  115. package/test/utils/FeeEstimatorHook.sol +84 -0
  116. package/test/utils/ProxyShim.sol +17 -0
  117. package/wagmi.config.ts +4 -0
  118. package/.env +0 -1
  119. package/.turbo/turbo-update-contract-version.log +0 -22
  120. package/abis/CoinSetupV3.json +0 -7
  121. package/abis/HookDeployer.json +0 -68
  122. package/abis/IHookDeployer.json +0 -42
  123. package/src/libs/CoinLegacy.sol +0 -48
  124. package/src/libs/CoinLegacyMarket.sol +0 -182
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zoralabs/coins",
3
- "version": "0.9.0",
3
+ "version": "1.0.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -21,18 +21,23 @@
21
21
  "@types/node": "^20.1.2",
22
22
  "@wagmi/cli": "^1.0.1",
23
23
  "@solidity-parser/parser": "0.19.0",
24
+ "@uniswap/v4-core": "https://github.com/Uniswap/v4-core#a7cf038cd568801a79a9b4cf92cd5b52c95c8585",
25
+ "@uniswap/v4-periphery": "https://github.com/Uniswap/v4-periphery#eeb3eff28dd5f5f17aa94180fa3610ff59b0e1c8",
26
+ "@uniswap/universal-router": "https://github.com/Uniswap/universal-router#3663f6db6e2fe121753cd2d899699c2dc75dca86",
27
+ "@uniswap/permit2": "https://github.com/Uniswap/permit2#cc56ad0f3439c502c246fc5cfcc3db92bb8b7219",
24
28
  "ds-test": "https://github.com/dapphub/ds-test#cd98eff28324bfac652e63a239a60632a761790b",
25
29
  "forge-std": "https://github.com/foundry-rs/forge-std#v1.9.1",
26
30
  "prettier": "^3.0.3",
27
31
  "prettier-plugin-solidity": "^1.4.1",
28
32
  "solady": "0.0.132",
33
+ "solmate": "6.8.0",
29
34
  "tsup": "^7.2.0",
30
35
  "tsx": "^3.13.0",
31
36
  "typescript": "^5.2.2",
32
37
  "viem": "^2.21.18",
33
38
  "@zoralabs/shared-contracts": "^0.0.3",
34
- "@zoralabs/tsconfig": "^0.0.1",
35
- "@zoralabs/shared-scripts": "^0.0.0"
39
+ "@zoralabs/shared-scripts": "^0.0.0",
40
+ "@zoralabs/tsconfig": "^0.0.1"
36
41
  },
37
42
  "scripts": {
38
43
  "build": "pnpm run wagmi:generate && pnpm run copy-abis && pnpm run prettier:write && tsup",
package/remappings.txt CHANGED
@@ -2,4 +2,9 @@ ds-test/=node_modules/ds-test/src/
2
2
  forge-std/=node_modules/forge-std/src/
3
3
  @openzeppelin/=node_modules/@openzeppelin/
4
4
  @zoralabs/shared-contracts/=node_modules/@zoralabs/shared-contracts/src/
5
- solady/=node_modules/solady/src/
5
+ solady/=node_modules/solady/src/
6
+ @uniswap/v4-core/=node_modules/@uniswap/v4-core/
7
+ @uniswap/v4-periphery/=node_modules/@uniswap/v4-periphery/
8
+ permit2/src/=node_modules/@uniswap/permit2/src/
9
+ @uniswap/universal-router/contracts/=node_modules/@uniswap/universal-router/contracts/
10
+ solmate/=node_modules/solmate/src/
@@ -8,8 +8,15 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/U
8
8
  import {ZoraFactoryImpl} from "../src/ZoraFactoryImpl.sol";
9
9
  import {Coin} from "../src/Coin.sol";
10
10
  import {IVersionedContract} from "@zoralabs/shared-contracts/interfaces/IVersionedContract.sol";
11
- import {BuySupplyWithSwapRouterHook} from "../src/hooks/BuySupplyWithSwapRouterHook.sol";
11
+ import {BuySupplyWithSwapRouterHook} from "../src/hooks/deployment/BuySupplyWithSwapRouterHook.sol";
12
12
  import {IZoraFactory} from "../src/interfaces/IZoraFactory.sol";
13
+ import {CoinV4} from "../src/CoinV4.sol";
14
+ import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
15
+ import {ZoraV4CoinHook} from "../src/hooks/ZoraV4CoinHook.sol";
16
+ import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
17
+ import {ZoraFactory} from "../src/proxy/ZoraFactory.sol";
18
+ import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
19
+ import {HooksDeployment} from "../src/libs/HooksDeployment.sol";
13
20
 
14
21
  contract CoinsDeployerBase is ProxyDeployerScript {
15
22
  address internal constant PROTOCOL_REWARDS = 0x7777777F279eba3d3Ad8F4E708545291A6fDBA8B;
@@ -21,10 +28,14 @@ contract CoinsDeployerBase is ProxyDeployerScript {
21
28
  address zoraFactory;
22
29
  address zoraFactoryImpl;
23
30
  // Implementation
24
- address coinImpl;
31
+ address coinV3Impl;
32
+ address coinV4Impl;
25
33
  string coinVersion;
26
34
  // hooks
27
35
  address buySupplyWithSwapRouterHook;
36
+ address zoraV4CoinHook;
37
+ address devFactory;
38
+ address trustedMessageSenders;
28
39
  }
29
40
 
30
41
  function addressesFile() internal view returns (string memory) {
@@ -38,7 +49,11 @@ contract CoinsDeployerBase is ProxyDeployerScript {
38
49
  vm.serializeAddress(objectKey, "ZORA_FACTORY_IMPL", deployment.zoraFactoryImpl);
39
50
  vm.serializeString(objectKey, "COIN_VERSION", deployment.coinVersion);
40
51
  vm.serializeAddress(objectKey, "BUY_SUPPLY_WITH_SWAP_ROUTER_HOOK", deployment.buySupplyWithSwapRouterHook);
41
- string memory result = vm.serializeAddress(objectKey, "COIN_IMPL", deployment.coinImpl);
52
+ vm.serializeAddress(objectKey, "COIN_V3_IMPL", deployment.coinV3Impl);
53
+ vm.serializeAddress(objectKey, "DEV_FACTORY", deployment.devFactory);
54
+ vm.serializeAddress(objectKey, "ZORA_V4_COIN_HOOK", deployment.zoraV4CoinHook);
55
+ vm.serializeAddress(objectKey, "TRUSTED_MESSAGE_SENDERS", deployment.trustedMessageSenders);
56
+ string memory result = vm.serializeAddress(objectKey, "COIN_V4_IMPL", deployment.coinV4Impl);
42
57
 
43
58
  vm.writeJson(result, addressesFile());
44
59
  }
@@ -52,28 +67,66 @@ contract CoinsDeployerBase is ProxyDeployerScript {
52
67
 
53
68
  deployment.zoraFactory = readAddressOrDefaultToZero(json, "ZORA_FACTORY");
54
69
  deployment.zoraFactoryImpl = readAddressOrDefaultToZero(json, "ZORA_FACTORY_IMPL");
55
- deployment.coinImpl = readAddressOrDefaultToZero(json, "COIN_IMPL");
70
+ deployment.coinV3Impl = readAddressOrDefaultToZero(json, "COIN_V3_IMPL");
71
+ deployment.coinV4Impl = readAddressOrDefaultToZero(json, "COIN_V4_IMPL");
56
72
  deployment.coinVersion = readStringOrDefaultToEmpty(json, "COIN_VERSION");
57
73
  deployment.buySupplyWithSwapRouterHook = readAddressOrDefaultToZero(json, "BUY_SUPPLY_WITH_SWAP_ROUTER_HOOK");
74
+ deployment.zoraV4CoinHook = readAddressOrDefaultToZero(json, "ZORA_V4_COIN_HOOK");
75
+ deployment.devFactory = readAddressOrDefaultToZero(json, "DEV_FACTORY");
76
+ deployment.trustedMessageSenders = readAddressOrDefaultToZero(json, "TRUSTED_MESSAGE_SENDERS");
58
77
  }
59
78
 
60
- function deployCoinImpl() internal returns (Coin) {
61
- return new Coin(getZoraRecipient(), PROTOCOL_REWARDS, getWeth(), getUniswapV3Factory(), getUniswapSwapRouter(), getDopplerAirlock());
79
+ function deployCoinV3Impl() internal returns (Coin) {
80
+ return
81
+ new Coin({
82
+ protocolRewardRecipient_: getZoraRecipient(),
83
+ protocolRewards_: PROTOCOL_REWARDS,
84
+ weth_: getWeth(),
85
+ v3Factory_: getUniswapV3Factory(),
86
+ swapRouter_: getUniswapSwapRouter(),
87
+ airlock_: getDopplerAirlock()
88
+ });
62
89
  }
63
90
 
64
- function deployZoraFactoryImpl(address coinImpl) internal returns (ZoraFactoryImpl) {
65
- return new ZoraFactoryImpl(coinImpl);
91
+ function deployCoinV4Impl(address zoraV4CoinHook) internal returns (CoinV4) {
92
+ return
93
+ new CoinV4({
94
+ protocolRewardRecipient_: getZoraRecipient(),
95
+ protocolRewards_: PROTOCOL_REWARDS,
96
+ poolManager_: IPoolManager(getUniswapV4PoolManager()),
97
+ airlock_: getDopplerAirlock(),
98
+ hooks_: IHooks(zoraV4CoinHook)
99
+ });
100
+ }
101
+
102
+ function deployZoraFactoryImpl(address coinV3Impl, address coinV4Impl) internal returns (ZoraFactoryImpl) {
103
+ return new ZoraFactoryImpl(coinV3Impl, coinV4Impl);
66
104
  }
67
105
 
68
106
  function deployBuySupplyWithSwapRouterHook(CoinsDeployment memory deployment) internal returns (BuySupplyWithSwapRouterHook) {
69
107
  return new BuySupplyWithSwapRouterHook(IZoraFactory(deployment.zoraFactory), getUniswapSwapRouter());
70
108
  }
71
109
 
110
+ function deployZoraV4CoinHook(address zoraFactory) internal returns (IHooks) {
111
+ return HooksDeployment.deployZoraV4CoinHookFromScript(getUniswapV4PoolManager(), zoraFactory, getDefaultTrustedMessageSenders());
112
+ }
113
+
114
+ function getDefaultTrustedMessageSenders() internal view returns (address[] memory) {
115
+ address[] memory trustedMessageSenders = new address[](2);
116
+ trustedMessageSenders[0] = getUniswapUniversalRouter();
117
+ trustedMessageSenders[1] = getUniswapV4PositionManager();
118
+ return trustedMessageSenders;
119
+ }
120
+
72
121
  function deployImpls(CoinsDeployment memory deployment) internal returns (CoinsDeployment memory) {
122
+ address zoraFactoryImpl = address(deployZoraFactoryImpl(deployment.coinV3Impl, deployment.coinV4Impl));
123
+
73
124
  // Deploy implementation contracts
74
- deployment.coinImpl = address(deployCoinImpl());
75
- deployment.zoraFactoryImpl = address(deployZoraFactoryImpl(deployment.coinImpl));
76
- deployment.coinVersion = IVersionedContract(deployment.coinImpl).contractVersion();
125
+ deployment.coinV3Impl = address(deployCoinV3Impl());
126
+ deployment.zoraV4CoinHook = address(deployZoraV4CoinHook(zoraFactoryImpl));
127
+ deployment.coinV4Impl = address(deployCoinV4Impl(deployment.zoraV4CoinHook));
128
+ deployment.zoraFactoryImpl = zoraFactoryImpl;
129
+ deployment.coinVersion = IVersionedContract(deployment.coinV3Impl).contractVersion();
77
130
  deployment.buySupplyWithSwapRouterHook = address(deployBuySupplyWithSwapRouterHook(deployment));
78
131
 
79
132
  return deployment;
@@ -113,6 +166,16 @@ contract CoinsDeployerBase is ProxyDeployerScript {
113
166
  require(ZoraFactoryImpl(deployment.zoraFactory).owner() == getProxyAdmin(), "Zora factory owner is not the proxy admin");
114
167
  }
115
168
 
169
+ function deployDevFactory(CoinsDeployment memory deployment) internal returns (ZoraFactory devFactory) {
170
+ address owner = 0x63545B401283c993320A5b886ecF0fc6CB5668a9;
171
+
172
+ devFactory = new ZoraFactory(deployment.zoraFactoryImpl);
173
+
174
+ ZoraFactoryImpl(address(devFactory)).initialize(owner);
175
+
176
+ deployment.devFactory = address(devFactory);
177
+ }
178
+
116
179
  function printUpgradeFactoryCommand(CoinsDeployment memory deployment) internal view {
117
180
  // build upgrade to and call for factory, with init call
118
181
  bytes memory call = abi.encodeWithSelector(UUPSUpgradeable.upgradeToAndCall.selector, deployment.zoraFactoryImpl, "");
@@ -0,0 +1,21 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.28;
3
+
4
+ import {ProxyDeployerScript, DeterministicDeployerAndCaller} from "@zoralabs/shared-contracts/deployment/ProxyDeployerScript.sol";
5
+ import {CoinsDeployerBase} from "./CoinsDeployerBase.sol";
6
+
7
+ contract DeployScript is CoinsDeployerBase {
8
+ function run() public {
9
+ CoinsDeployment memory deployment = readDeployment();
10
+
11
+ vm.startBroadcast();
12
+
13
+ // get deployer contract
14
+ deployDevFactory(deployment);
15
+
16
+ vm.stopBroadcast();
17
+
18
+ // save the deployment json
19
+ saveDeployment(deployment);
20
+ }
21
+ }
@@ -0,0 +1,13 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.26;
3
+
4
+ import {ProxyDeployerScript, DeterministicDeployerAndCaller} from "@zoralabs/shared-contracts/deployment/ProxyDeployerScript.sol";
5
+ import {CoinsDeployerBase} from "./CoinsDeployerBase.sol";
6
+
7
+ contract PrintUpgradeCommand is CoinsDeployerBase {
8
+ function run() public {
9
+ CoinsDeployment memory deployment = readDeployment();
10
+
11
+ printUpgradeFactoryCommand(deployment);
12
+ }
13
+ }
@@ -42,16 +42,7 @@ contract Simulate is Script {
42
42
 
43
43
  // Prebuy order size
44
44
  uint256 orderSize = 0.000111 ether;
45
- (address coinAddress, uint256 coinsPurchased) = factory.deploy{value: orderSize}(
46
- payoutAddress,
47
- owners,
48
- uri,
49
- name,
50
- symbol,
51
- poolConfig,
52
- payoutAddress,
53
- orderSize
54
- );
45
+ factory.deploy{value: orderSize}(payoutAddress, owners, uri, name, symbol, poolConfig, payoutAddress, orderSize);
55
46
 
56
47
  vm.stopBroadcast();
57
48
  }
@@ -0,0 +1,146 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.28;
3
+
4
+ import {ProxyDeployerScript, DeterministicDeployerAndCaller} from "@zoralabs/shared-contracts/deployment/ProxyDeployerScript.sol";
5
+ import {CoinsDeployerBase} from "./CoinsDeployerBase.sol";
6
+
7
+ import {IZoraFactory} from "../src/interfaces/IZoraFactory.sol";
8
+ import {CoinConfigurationVersions} from "../src/libs/CoinConfigurationVersions.sol";
9
+ import {MarketConstants} from "../src/libs/MarketConstants.sol";
10
+ import {UniV4SwapHelper} from "../src/libs/UniV4SwapHelper.sol";
11
+ import {CoinV4} from "../src/CoinV4.sol";
12
+ import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
13
+ import {IUniversalRouter} from "@uniswap/universal-router/contracts/interfaces/IUniversalRouter.sol";
14
+ import {IPermit2} from "permit2/src/interfaces/IPermit2.sol";
15
+ import {MockERC20} from "../test/mocks/MockERC20.sol";
16
+ import {MarketConstants} from "../src/libs/MarketConstants.sol";
17
+ import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
18
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
19
+ import {ICoinV4} from "../src/interfaces/ICoinV4.sol";
20
+
21
+ import {console} from "forge-std/console.sol";
22
+
23
+ contract TestV4Swap is CoinsDeployerBase {
24
+ int24 internal constant DEFAULT_DISCOVERY_TICK_LOWER = -777000;
25
+ int24 internal constant DEFAULT_DISCOVERY_TICK_UPPER = 222000;
26
+ uint16 internal constant DEFAULT_NUM_DISCOVERY_POSITIONS = 10; // will be 11 total with tail position
27
+ uint256 internal constant DEFAULT_DISCOVERY_SUPPLY_SHARE = 0.495e18; //
28
+
29
+ function _deployCoin(
30
+ address currency,
31
+ address creator,
32
+ string memory name,
33
+ string memory symbol,
34
+ string memory uri,
35
+ address createReferral,
36
+ bytes32 salt
37
+ ) internal returns (ICoinV4 coin) {
38
+ CoinsDeployment memory deployment = readDeployment();
39
+ address[] memory owners = new address[](1);
40
+ owners[0] = creator;
41
+
42
+ bytes memory poolConfig = CoinConfigurationVersions.defaultDopplerMultiCurveUniV4(address(currency));
43
+
44
+ (address coinAddress, ) = IZoraFactory(deployment.devFactory).deploy(
45
+ creator,
46
+ owners,
47
+ uri,
48
+ name,
49
+ symbol,
50
+ poolConfig,
51
+ createReferral,
52
+ address(0),
53
+ "",
54
+ salt
55
+ );
56
+
57
+ coin = ICoinV4(coinAddress);
58
+ }
59
+
60
+ function _swap(address currencyIn, uint128 amountIn, ICoinV4 coin, address trader, address tradeReferral) internal returns (uint256 amountOut) {
61
+ uint128 minAmountOut = 0;
62
+
63
+ PoolKey memory poolKey = coin.getPoolKey();
64
+
65
+ bytes memory hookData = tradeReferral != address(0) ? abi.encode(tradeReferral) : bytes("");
66
+
67
+ address currencyOut = Currency.unwrap(Currency.unwrap(poolKey.currency0) == currencyIn ? poolKey.currency1 : poolKey.currency0);
68
+
69
+ // now we need to swap some currency into the coin
70
+ // first let
71
+ (bytes memory commands, bytes[] memory inputs) = UniV4SwapHelper.buildExactInputSingleSwapCommand(
72
+ currencyIn,
73
+ amountIn,
74
+ currencyOut,
75
+ minAmountOut,
76
+ poolKey,
77
+ hookData
78
+ );
79
+
80
+ UniV4SwapHelper.approveTokenWithPermit2(
81
+ IPermit2(getUniswapPermit2()),
82
+ getUniswapUniversalRouter(),
83
+ currencyIn,
84
+ amountIn,
85
+ uint48(block.timestamp + 1 days)
86
+ );
87
+
88
+ uint256 balanceBefore = IERC20(currencyOut).balanceOf(trader);
89
+
90
+ // Execute the swap
91
+ uint256 deadline = block.timestamp + 1 days;
92
+ IUniversalRouter(getUniswapUniversalRouter()).execute(commands, inputs, deadline);
93
+
94
+ amountOut = IERC20(currencyOut).balanceOf(trader) - balanceBefore;
95
+ }
96
+
97
+ function run() public {
98
+ address trader = vm.envAddress("TRADER");
99
+
100
+ require(block.chainid == 8453, "only on base");
101
+
102
+ address zora = 0x1111111111166b7FE7bd91427724B487980aFc69;
103
+
104
+ vm.startBroadcast(trader);
105
+
106
+ // address createReferral = 0xC077e4cC02fa01A5b7fAca1acE9BBe9f5ac5Af9F;
107
+ address tradeReferral = 0xC077e4cC02fa01A5b7fAca1acE9BBe9f5ac5Af9F;
108
+ // ICoinV4 backingCoin = _deployCoin(zora, trader, "TestCCoin", "CRE", "https://testc.com", createReferral, bytes32("creator"));
109
+ // ICoinV4 contentCoin = _deployCoin(
110
+ // address(backingCoin),
111
+ // trader,
112
+ // "Content Coin",
113
+ // "CONTENT",
114
+ // "https://content.com",
115
+ // createReferral,
116
+ // bytes32("content coin")
117
+ // );
118
+ ICoinV4 backingCoin = ICoinV4(0xeA734b5997F35cD469921cCa7BB9A03C104f2f64);
119
+ ICoinV4 contentCoin = ICoinV4(0x72218BFEEc7D556BD3Dd8eFf2a317CEd49533769);
120
+
121
+ console.log("backingCoin", address(backingCoin));
122
+ console.log("contentCoin", address(contentCoin));
123
+ // console.log("currency", address(currency));
124
+
125
+ // (MockERC20 currency, address coinAddress) = _deployMockCurrencyAndCoin(trader, createReferral);
126
+
127
+ // address coinAddress = vm.parseAddress("0x58c0d8803Ae97bEF212EdFA8ba2FE303670cca9D");
128
+ // console.log("currency", address(currency));
129
+ // console.log("coinAddress", coinAddress);
130
+
131
+ // swap in 2 ether of currency into the coin
132
+ uint128 amountIn = uint128(IERC20(zora).balanceOf(trader));
133
+ // currency.mint(trader, amountIn);
134
+
135
+ // // swap some currency into the backing coin
136
+ uint256 backingCoinReceived = _swap(zora, amountIn, backingCoin, trader, tradeReferral);
137
+
138
+ // // swap balance of backing coin into the content coin
139
+ uint256 contentCoinReceived = _swap(address(backingCoin), uint128(backingCoinReceived), contentCoin, trader, tradeReferral);
140
+
141
+ // swap balance of content coin into the currency
142
+ _swap(address(contentCoin), uint128(contentCoinReceived), contentCoin, trader, tradeReferral);
143
+
144
+ vm.stopBroadcast();
145
+ }
146
+ }
@@ -0,0 +1,136 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.28;
3
+
4
+ import {ProxyDeployerScript, DeterministicDeployerAndCaller} from "@zoralabs/shared-contracts/deployment/ProxyDeployerScript.sol";
5
+ import {CoinsDeployerBase} from "./CoinsDeployerBase.sol";
6
+
7
+ import {IZoraFactory} from "../src/interfaces/IZoraFactory.sol";
8
+ import {CoinConfigurationVersions} from "../src/libs/CoinConfigurationVersions.sol";
9
+ import {MarketConstants} from "../src/libs/MarketConstants.sol";
10
+ import {UniV4SwapHelper} from "../src/libs/UniV4SwapHelper.sol";
11
+ import {CoinV4} from "../src/CoinV4.sol";
12
+ import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
13
+ import {IUniversalRouter} from "@uniswap/universal-router/contracts/interfaces/IUniversalRouter.sol";
14
+ import {IPermit2} from "permit2/src/interfaces/IPermit2.sol";
15
+ import {MockERC20} from "../test/mocks/MockERC20.sol";
16
+ import {MarketConstants} from "../src/libs/MarketConstants.sol";
17
+ import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
18
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
19
+ import {ICoinV4} from "../src/interfaces/ICoinV4.sol";
20
+
21
+ import {console} from "forge-std/console.sol";
22
+
23
+ contract TestV4Swap is CoinsDeployerBase {
24
+ int24 internal constant DEFAULT_DISCOVERY_TICK_LOWER = -777000;
25
+ int24 internal constant DEFAULT_DISCOVERY_TICK_UPPER = 222000;
26
+ uint16 internal constant DEFAULT_NUM_DISCOVERY_POSITIONS = 10; // will be 11 total with tail position
27
+ uint256 internal constant DEFAULT_DISCOVERY_SUPPLY_SHARE = 0.495e18; //
28
+
29
+ function _deployMockCurrency() internal returns (MockERC20 currency) {
30
+ currency = new MockERC20("Testcoin", "TEST");
31
+ currency.mint(getUniswapV4PoolManager(), 1000000 ether);
32
+ }
33
+
34
+ function _deployMockCoin(address currency, address creator, address createReferral, bytes32 salt) internal returns (ICoinV4 coin) {
35
+ CoinsDeployment memory deployment = readDeployment();
36
+ address[] memory owners = new address[](1);
37
+ owners[0] = creator;
38
+
39
+ bytes memory poolConfig = CoinConfigurationVersions.defaultDopplerMultiCurveUniV4(address(currency));
40
+
41
+ (address coinAddress, ) = IZoraFactory(deployment.zoraFactory).deploy(
42
+ creator,
43
+ owners,
44
+ "https://test.com",
45
+ "Testcoin",
46
+ "TEST",
47
+ poolConfig,
48
+ createReferral,
49
+ address(0),
50
+ "",
51
+ salt
52
+ );
53
+
54
+ coin = ICoinV4(coinAddress);
55
+ }
56
+
57
+ function _swap(address currencyIn, uint128 amountIn, ICoinV4 coin, address trader, address tradeReferral) internal returns (uint256 amountOut) {
58
+ uint128 minAmountOut = 0;
59
+
60
+ PoolKey memory poolKey = coin.getPoolKey();
61
+
62
+ bytes memory hookData = tradeReferral != address(0) ? abi.encode(tradeReferral) : bytes("");
63
+
64
+ address currencyOut = Currency.unwrap(Currency.unwrap(poolKey.currency0) == currencyIn ? poolKey.currency1 : poolKey.currency0);
65
+
66
+ // now we need to swap some currency into the coin
67
+ // first let
68
+ (bytes memory commands, bytes[] memory inputs) = UniV4SwapHelper.buildExactInputSingleSwapCommand(
69
+ currencyIn,
70
+ amountIn,
71
+ currencyOut,
72
+ minAmountOut,
73
+ poolKey,
74
+ hookData
75
+ );
76
+
77
+ UniV4SwapHelper.approveTokenWithPermit2(
78
+ IPermit2(getUniswapPermit2()),
79
+ getUniswapUniversalRouter(),
80
+ currencyIn,
81
+ amountIn,
82
+ uint48(block.timestamp + 1 days)
83
+ );
84
+
85
+ uint256 balanceBefore = IERC20(currencyOut).balanceOf(trader);
86
+
87
+ // Execute the swap
88
+ uint256 deadline = block.timestamp + 1 days;
89
+ IUniversalRouter(getUniswapUniversalRouter()).execute(commands, inputs, deadline);
90
+
91
+ amountOut = IERC20(currencyOut).balanceOf(trader) - balanceBefore;
92
+ }
93
+
94
+ function run() public {
95
+ address trader = vm.envAddress("TRADER");
96
+
97
+ vm.startBroadcast(trader);
98
+
99
+ // address createReferral = 0xC077e4cC02fa01A5b7fAca1acE9BBe9f5ac5Af9F;
100
+ address tradeReferral = 0xC077e4cC02fa01A5b7fAca1acE9BBe9f5ac5Af9F;
101
+
102
+ // MockERC20 currency = _deployMockCurrency();
103
+
104
+ // ICoinV4 backingCoin = _deployMockCoin(address(currency), trader, createReferral, bytes32("backing coin"));
105
+ // ICoinV4 contentCoin = _deployMockCoin(address(backingCoin), trader, createReferral, bytes32("content coin"));
106
+
107
+ MockERC20 currency = MockERC20(0x21E3bde504fF56C440851ACB6A16e7E35405B278);
108
+ ICoinV4 backingCoin = ICoinV4(0xa8bb679A2be09eCCabdb76700170ec387C896570);
109
+ ICoinV4 contentCoin = ICoinV4(0x3cfE4CE87A821FB2c7eAB4359dD6eA6F9e492c61);
110
+
111
+ console.log("backingCoin", address(backingCoin));
112
+ console.log("contentCoin", address(contentCoin));
113
+ console.log("currency", address(currency));
114
+
115
+ // (MockERC20 currency, address coinAddress) = _deployMockCurrencyAndCoin(trader, createReferral);
116
+
117
+ // address coinAddress = vm.parseAddress("0x58c0d8803Ae97bEF212EdFA8ba2FE303670cca9D");
118
+ // console.log("currency", address(currency));
119
+ // console.log("coinAddress", coinAddress);
120
+
121
+ // swap in 2 ether of currency into the coin
122
+ uint128 amountIn = 2 ether;
123
+ currency.mint(trader, amountIn);
124
+
125
+ // swap some currency into the backing coin
126
+ uint256 backingCoinReceived = _swap(address(currency), amountIn, backingCoin, trader, tradeReferral);
127
+
128
+ // swap balance of backing coin into the content coin
129
+ uint256 contentCoinReceived = _swap(address(backingCoin), uint128(backingCoinReceived), contentCoin, trader, tradeReferral);
130
+
131
+ // swap balance of content coin into the currency
132
+ _swap(address(contentCoin), uint128(contentCoinReceived), contentCoin, trader, tradeReferral);
133
+
134
+ vm.stopBroadcast();
135
+ }
136
+ }
@@ -10,7 +10,7 @@ contract UpgradeFactoryImpl is CoinsDeployerBase {
10
10
 
11
11
  vm.startBroadcast();
12
12
 
13
- ZoraFactoryImpl zoraFactoryImpl = deployZoraFactoryImpl(deployment.coinImpl);
13
+ ZoraFactoryImpl zoraFactoryImpl = deployZoraFactoryImpl(deployment.coinV3Impl, deployment.coinV4Impl);
14
14
 
15
15
  deployment.zoraFactoryImpl = address(zoraFactoryImpl);
16
16