@zoralabs/coins 0.9.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +179 -114
- package/CHANGELOG.md +46 -0
- package/abis/BaseCoin.json +26 -118
- package/abis/BaseTest.json +47 -0
- package/abis/BuySupplyWithSwapRouterHook.json +40 -0
- package/abis/Coin.json +171 -63
- package/abis/CoinDopplerMultiCurve.json +38 -0
- package/abis/CoinRewardsV4.json +54 -0
- package/abis/CoinTest.json +53 -20
- package/abis/CoinUniV4Test.json +1091 -0
- package/abis/CoinV4.json +234 -211
- package/abis/DeployScript.json +47 -0
- package/abis/DeployedCoinVersionLookup.json +21 -0
- package/abis/DeployedCoinVersionLookupTest.json +716 -0
- package/abis/DifferentNamespaceVersionLookup.json +39 -0
- package/abis/DopplerUniswapV3Test.json +49 -93
- package/abis/ERC20.json +310 -0
- package/abis/FactoryTest.json +85 -7
- package/abis/FeeEstimatorHook.json +1515 -0
- package/abis/HooksDeployment.json +23 -0
- package/abis/HooksTest.json +60 -0
- package/abis/ICoin.json +40 -71
- package/abis/ICoinV3.json +879 -0
- package/abis/ICoinV4.json +915 -0
- package/abis/IDeployedCoinVersionLookup.json +21 -0
- package/abis/IERC721.json +36 -36
- package/abis/IHasPoolKey.json +42 -0
- package/abis/IHasRewardsRecipients.json +54 -0
- package/abis/IHasSwapPath.json +60 -0
- package/abis/IMsgSender.json +15 -0
- package/abis/IPoolConfigEncoding.json +46 -0
- package/abis/ISwapPathRouter.json +92 -0
- package/abis/IUniversalRouter.json +61 -0
- package/abis/IUnlockCallback.json +21 -0
- package/abis/IV4Quoter.json +310 -0
- package/abis/IZoraFactory.json +210 -11
- package/abis/IZoraV4CoinHook.json +348 -4
- package/abis/MockERC20.json +21 -0
- package/abis/MultiOwnableTest.json +47 -0
- package/abis/{CoinConfigurationVersions.json → Position.json} +1 -1
- package/abis/PrintUpgradeCommand.json +9 -0
- package/abis/ProxyShim.json +24 -0
- package/abis/StateLibrary.json +80 -0
- package/abis/TestDeployedCoinVersionLookupImplementation.json +39 -0
- package/abis/TestV4Swap.json +9 -0
- package/abis/UpgradeCoinImpl.json +47 -0
- package/abis/UpgradesTest.json +81 -0
- package/abis/Vm.json +1482 -111
- package/abis/VmSafe.json +856 -32
- package/abis/ZoraFactoryImpl.json +339 -1
- package/abis/ZoraV4CoinHook.json +442 -5
- package/addresses/8453.json +7 -4
- package/addresses/84532.json +8 -5
- package/addresses/dev/8453.json +10 -0
- package/dist/index.cjs +1932 -167
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1928 -167
- package/dist/index.js.map +1 -1
- package/dist/wagmiGenerated.d.ts +2606 -160
- package/dist/wagmiGenerated.d.ts.map +1 -1
- package/foundry.toml +1 -0
- package/package/wagmiGenerated.ts +1941 -164
- package/package.json +8 -3
- package/remappings.txt +6 -1
- package/script/Deploy.s.sol +1 -1
- package/script/DeployDevFactory.s.sol +21 -0
- package/script/DeployHooks.s.sol +1 -1
- package/script/PrintUpgradeCommand.s.sol +13 -0
- package/script/Simulate.s.sol +1 -10
- package/script/TestBackingCoinSwap.s.sol +147 -0
- package/script/TestV4Swap.s.sol +136 -0
- package/script/UpgradeCoinImpl.sol +2 -2
- package/script/UpgradeFactoryImpl.s.sol +2 -2
- package/src/BaseCoin.sol +190 -0
- package/src/Coin.sol +87 -202
- package/src/CoinV4.sol +121 -0
- package/src/ZoraFactoryImpl.sol +208 -36
- package/{script → src/deployment}/CoinsDeployerBase.sol +111 -17
- package/src/hooks/ZoraV4CoinHook.sol +212 -0
- package/src/hooks/{BaseCoinDeployHook.sol → deployment/BaseCoinDeployHook.sol} +3 -3
- package/src/hooks/deployment/BuySupplyWithSwapRouterHook.sol +140 -0
- package/src/interfaces/ICoin.sol +31 -39
- package/src/interfaces/ICoinV3.sol +71 -0
- package/src/interfaces/ICoinV4.sol +69 -0
- package/src/interfaces/IDeployedCoinVersionLookup.sol +11 -0
- package/src/interfaces/IMsgSender.sol +9 -0
- package/src/interfaces/IPoolConfigEncoding.sol +14 -0
- package/src/interfaces/ISwapPathRouter.sol +14 -0
- package/src/interfaces/IZoraFactory.sol +67 -28
- package/src/interfaces/IZoraV4CoinHook.sol +116 -0
- package/src/libs/CoinCommon.sol +15 -0
- package/src/libs/CoinConfigurationVersions.sol +116 -1
- package/src/libs/CoinConstants.sol +5 -0
- package/src/libs/CoinDopplerMultiCurve.sol +134 -0
- package/src/libs/CoinDopplerUniV3.sol +19 -171
- package/src/libs/CoinRewards.sol +195 -0
- package/src/libs/CoinRewardsV4.sol +179 -0
- package/src/libs/CoinSetup.sol +57 -0
- package/src/libs/CoinSetupV3.sol +6 -67
- package/src/libs/DopplerMath.sol +156 -0
- package/src/libs/HooksDeployment.sol +128 -0
- package/src/libs/MarketConstants.sol +4 -0
- package/src/libs/PoolStateReader.sol +22 -0
- package/src/libs/UniV3BuySell.sol +74 -292
- package/src/libs/UniV4SwapHelper.sol +65 -0
- package/src/libs/UniV4SwapToCurrency.sol +109 -0
- package/src/libs/V4Liquidity.sol +122 -0
- package/src/types/PoolConfiguration.sol +15 -0
- package/src/utils/DeployedCoinVersionLookup.sol +52 -0
- package/src/version/ContractVersionBase.sol +1 -1
- package/test/Coin.t.sol +78 -88
- package/test/CoinDopplerUniV3.t.sol +32 -171
- package/test/CoinUniV4.t.sol +777 -0
- package/test/{Hooks.t.sol → DeploymentHooks.t.sol} +53 -16
- package/test/Factory.t.sol +80 -47
- package/test/MultiOwnable.t.sol +6 -3
- package/test/Upgrades.t.sol +97 -5
- package/test/mocks/MockERC20.sol +12 -0
- package/test/utils/BaseTest.sol +162 -57
- package/test/utils/DeployedCoinVersionLookup.t.sol +127 -0
- package/test/utils/FeeEstimatorHook.sol +84 -0
- package/test/utils/ProxyShim.sol +17 -0
- package/wagmi.config.ts +4 -0
- package/.env +0 -1
- package/.turbo/turbo-update-contract-version.log +0 -22
- package/abis/CoinSetupV3.json +0 -7
- package/abis/HookDeployer.json +0 -68
- package/abis/IHookDeployer.json +0 -42
- package/src/hooks/BuySupplyWithSwapRouterHook.sol +0 -78
- package/src/libs/CoinLegacy.sol +0 -48
- package/src/libs/CoinLegacyMarket.sol +0 -182
package/src/Coin.sol
CHANGED
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
pragma solidity ^0.8.23;
|
|
3
3
|
|
|
4
4
|
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
5
|
-
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
6
5
|
import {ICoin, PoolConfiguration} from "./interfaces/ICoin.sol";
|
|
7
|
-
import {ICoinComments} from "./interfaces/ICoinComments.sol";
|
|
8
|
-
import {IERC7572} from "./interfaces/IERC7572.sol";
|
|
9
6
|
import {IUniswapV3Factory} from "./interfaces/IUniswapV3Factory.sol";
|
|
10
7
|
import {IUniswapV3Pool} from "./interfaces/IUniswapV3Pool.sol";
|
|
11
8
|
import {ISwapRouter} from "./interfaces/ISwapRouter.sol";
|
|
@@ -19,15 +16,14 @@ import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/ut
|
|
|
19
16
|
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
20
17
|
import {ContractVersionBase} from "./version/ContractVersionBase.sol";
|
|
21
18
|
import {MultiOwnable} from "./utils/MultiOwnable.sol";
|
|
22
|
-
import {FullMath} from "./utils/uniswap/FullMath.sol";
|
|
23
|
-
import {TickMath} from "./utils/uniswap/TickMath.sol";
|
|
24
|
-
import {LiquidityAmounts} from "./utils/uniswap/LiquidityAmounts.sol";
|
|
25
19
|
import {CoinConstants} from "./libs/CoinConstants.sol";
|
|
26
20
|
import {MarketConstants} from "./libs/MarketConstants.sol";
|
|
27
21
|
import {LpPosition} from "./types/LpPosition.sol";
|
|
28
22
|
import {PoolState} from "./types/PoolState.sol";
|
|
29
23
|
import {CoinSetupV3, UniV3Config, CoinV3Config} from "./libs/CoinSetupV3.sol";
|
|
30
|
-
import {UniV3BuySell, CoinConfig} from "./libs/UniV3BuySell.sol";
|
|
24
|
+
import {UniV3BuySell, CoinConfig, SellResult} from "./libs/UniV3BuySell.sol";
|
|
25
|
+
import {BaseCoin} from "./BaseCoin.sol";
|
|
26
|
+
import {ICoinV3} from "./interfaces/ICoinV3.sol";
|
|
31
27
|
|
|
32
28
|
/*
|
|
33
29
|
$$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\
|
|
@@ -39,183 +35,98 @@ import {UniV3BuySell, CoinConfig} from "./libs/UniV3BuySell.sol";
|
|
|
39
35
|
\$$$$$$ | $$$$$$ |$$$$$$\ $$ | \$$ |
|
|
40
36
|
\______/ \______/ \______|\__| \__|
|
|
41
37
|
*/
|
|
42
|
-
contract Coin is
|
|
38
|
+
contract Coin is BaseCoin, ICoinV3 {
|
|
43
39
|
using SafeERC20 for IERC20;
|
|
44
40
|
|
|
45
|
-
/// @notice The address of the WETH contract
|
|
46
|
-
address public immutable WETH;
|
|
47
|
-
/// @notice The address of the Uniswap V3 factory
|
|
48
41
|
address public immutable v3Factory;
|
|
49
42
|
/// @notice The address of the Uniswap V3 swap router
|
|
50
43
|
address public immutable swapRouter;
|
|
51
|
-
/// @notice The address of the Airlock contract, ownership is used for a protocol fee split.
|
|
52
|
-
address public immutable airlock;
|
|
53
|
-
/// @notice The address of the protocol rewards contract
|
|
54
|
-
address public immutable protocolRewards;
|
|
55
|
-
/// @notice The address of the protocol reward recipient
|
|
56
|
-
address public immutable protocolRewardRecipient;
|
|
57
|
-
|
|
58
|
-
/// @notice The metadata URI
|
|
59
|
-
string public tokenURI;
|
|
60
|
-
/// @notice The address of the coin creator
|
|
61
|
-
address public payoutRecipient;
|
|
62
|
-
/// @notice The address of the platform referrer
|
|
63
|
-
address public platformReferrer;
|
|
64
44
|
/// @notice The address of the Uniswap V3 pool
|
|
65
45
|
address public poolAddress;
|
|
66
|
-
/// @notice The address of the currency
|
|
67
|
-
address public currency;
|
|
68
46
|
|
|
69
47
|
/// @notice The state of the market
|
|
70
48
|
bytes public market;
|
|
71
49
|
uint8 public marketVersion;
|
|
72
50
|
|
|
51
|
+
/// @notice The address of the WETH contract
|
|
52
|
+
address public immutable WETH;
|
|
53
|
+
|
|
73
54
|
/// @notice deprecated
|
|
74
55
|
PoolConfiguration public poolConfiguration;
|
|
75
56
|
|
|
76
|
-
|
|
77
|
-
/// @dev This is a legacy function for compatibility with doppler default state
|
|
78
|
-
/// @return asset The address of the asset
|
|
79
|
-
/// @return numeraire The address of the numeraire
|
|
80
|
-
/// @return tickLower The lower tick
|
|
81
|
-
/// @return tickUpper The upper tick
|
|
82
|
-
/// @return numPositions The number of discovery positions
|
|
83
|
-
/// @return isInitialized Whether the pool is initialized
|
|
84
|
-
/// @return isExited Whether the pool is exited
|
|
85
|
-
/// @return maxShareToBeSold The maximum share to be sold
|
|
86
|
-
/// @return totalTokensOnBondingCurve The total tokens on the bonding curve
|
|
87
|
-
function poolState()
|
|
88
|
-
external
|
|
89
|
-
view
|
|
90
|
-
returns (
|
|
91
|
-
address asset,
|
|
92
|
-
address numeraire,
|
|
93
|
-
int24 tickLower,
|
|
94
|
-
int24 tickUpper,
|
|
95
|
-
uint16 numPositions,
|
|
96
|
-
bool isInitialized,
|
|
97
|
-
bool isExited,
|
|
98
|
-
uint256 maxShareToBeSold,
|
|
99
|
-
uint256 totalTokensOnBondingCurve
|
|
100
|
-
)
|
|
101
|
-
{
|
|
102
|
-
asset = address(this);
|
|
103
|
-
numeraire = currency;
|
|
104
|
-
tickLower = poolConfiguration.tickLower;
|
|
105
|
-
tickUpper = poolConfiguration.tickUpper;
|
|
106
|
-
numPositions = poolConfiguration.numPositions;
|
|
107
|
-
isInitialized = true;
|
|
108
|
-
isExited = false;
|
|
109
|
-
maxShareToBeSold = poolConfiguration.maxDiscoverySupplyShare;
|
|
110
|
-
totalTokensOnBondingCurve = CoinConstants.POOL_LAUNCH_SUPPLY;
|
|
111
|
-
}
|
|
57
|
+
LpPosition[] public positions;
|
|
112
58
|
|
|
113
59
|
/**
|
|
114
60
|
* @notice The constructor for the static Coin contract deployment shared across all Coins.
|
|
115
|
-
* @param
|
|
116
|
-
* @param
|
|
117
|
-
* @param
|
|
118
|
-
* @param
|
|
119
|
-
* @param
|
|
120
|
-
* @param
|
|
61
|
+
* @param protocolRewardRecipient_ The address of the protocol reward recipient
|
|
62
|
+
* @param protocolRewards_ The address of the protocol rewards contract
|
|
63
|
+
* @param weth_ The address of the WETH contract
|
|
64
|
+
* @param v3Factory_ The address of the Uniswap V3 factory
|
|
65
|
+
* @param swapRouter_ The address of the Uniswap V3 swap router
|
|
66
|
+
* @param airlock_ The address of the Airlock contract, ownership is used for a protocol fee split.
|
|
121
67
|
*/
|
|
122
68
|
constructor(
|
|
123
|
-
address
|
|
124
|
-
address
|
|
125
|
-
address
|
|
126
|
-
address
|
|
127
|
-
address
|
|
128
|
-
address
|
|
129
|
-
) initializer {
|
|
130
|
-
if (
|
|
131
|
-
revert AddressZero();
|
|
132
|
-
}
|
|
133
|
-
if (_protocolRewards == address(0)) {
|
|
134
|
-
revert AddressZero();
|
|
135
|
-
}
|
|
136
|
-
if (_weth == address(0)) {
|
|
69
|
+
address protocolRewardRecipient_,
|
|
70
|
+
address protocolRewards_,
|
|
71
|
+
address weth_,
|
|
72
|
+
address v3Factory_,
|
|
73
|
+
address swapRouter_,
|
|
74
|
+
address airlock_
|
|
75
|
+
) BaseCoin(protocolRewardRecipient_, protocolRewards_, airlock_) initializer {
|
|
76
|
+
if (v3Factory_ == address(0)) {
|
|
137
77
|
revert AddressZero();
|
|
138
78
|
}
|
|
139
|
-
if (
|
|
79
|
+
if (swapRouter_ == address(0)) {
|
|
140
80
|
revert AddressZero();
|
|
141
81
|
}
|
|
142
|
-
if (
|
|
82
|
+
if (airlock_ == address(0)) {
|
|
143
83
|
revert AddressZero();
|
|
144
84
|
}
|
|
145
|
-
if (
|
|
85
|
+
if (weth_ == address(0)) {
|
|
146
86
|
revert AddressZero();
|
|
147
87
|
}
|
|
88
|
+
swapRouter = swapRouter_;
|
|
89
|
+
v3Factory = v3Factory_;
|
|
148
90
|
|
|
149
|
-
|
|
150
|
-
protocolRewards = _protocolRewards;
|
|
151
|
-
WETH = _weth;
|
|
152
|
-
swapRouter = _swapRouter;
|
|
153
|
-
v3Factory = _v3Factory;
|
|
154
|
-
airlock = _airlock;
|
|
91
|
+
WETH = weth_;
|
|
155
92
|
}
|
|
156
93
|
|
|
157
|
-
/// @
|
|
158
|
-
/// @param payoutRecipient_ The address of the coin creator
|
|
159
|
-
/// @param tokenURI_ The metadata URI
|
|
160
|
-
/// @param name_ The coin name
|
|
161
|
-
/// @param symbol_ The coin symbol
|
|
162
|
-
/// @param poolConfig_ The parameters for the v3 pool and liquidity
|
|
163
|
-
/// @param platformReferrer_ The address of the platform referrer
|
|
94
|
+
/// @inheritdoc ICoinV3
|
|
164
95
|
function initialize(
|
|
165
96
|
address payoutRecipient_,
|
|
166
97
|
address[] memory owners_,
|
|
167
98
|
string memory tokenURI_,
|
|
168
99
|
string memory name_,
|
|
169
100
|
string memory symbol_,
|
|
170
|
-
|
|
171
|
-
address
|
|
101
|
+
address platformReferrer_,
|
|
102
|
+
address currency_,
|
|
103
|
+
address poolAddress_,
|
|
104
|
+
PoolConfiguration memory poolConfiguration_,
|
|
105
|
+
LpPosition[] memory positions_
|
|
172
106
|
) public initializer {
|
|
173
|
-
|
|
174
|
-
if (payoutRecipient_ == address(0)) {
|
|
175
|
-
revert AddressZero();
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Set base contract state
|
|
179
|
-
__ERC20_init(name_, symbol_);
|
|
180
|
-
__ERC20Permit_init(name_);
|
|
181
|
-
__MultiOwnable_init(owners_);
|
|
182
|
-
__ReentrancyGuard_init();
|
|
183
|
-
|
|
184
|
-
// Set mutable state
|
|
185
|
-
_setPayoutRecipient(payoutRecipient_);
|
|
186
|
-
_setContractURI(tokenURI_);
|
|
107
|
+
super._initialize(payoutRecipient_, owners_, tokenURI_, name_, symbol_, platformReferrer_);
|
|
187
108
|
|
|
188
|
-
|
|
189
|
-
|
|
109
|
+
currency = currency_;
|
|
110
|
+
poolAddress = poolAddress_;
|
|
111
|
+
poolConfiguration = poolConfiguration_;
|
|
112
|
+
positions = positions_;
|
|
190
113
|
|
|
191
|
-
|
|
192
|
-
_mint(address(this), CoinConstants.MAX_TOTAL_SUPPLY);
|
|
193
|
-
|
|
194
|
-
// Distribute the creator launch reward
|
|
195
|
-
_transfer(address(this), payoutRecipient, CoinConstants.CREATOR_LAUNCH_REWARD);
|
|
196
|
-
|
|
197
|
-
UniV3Config memory uniswapV3Config = UniV3Config({weth: WETH, v3Factory: v3Factory, swapRouter: swapRouter, airlock: airlock});
|
|
198
|
-
|
|
199
|
-
// Deploy the pool
|
|
200
|
-
(currency, poolAddress, poolConfiguration) = CoinSetupV3.setupPool(poolConfig_, uniswapV3Config, address(this));
|
|
201
|
-
|
|
202
|
-
// Split out the deployment of liquidity to avoid stack too deep
|
|
203
|
-
CoinSetupV3.deployLiquidity(address(this), currency, poolConfiguration, poolAddress);
|
|
114
|
+
CoinSetupV3.deployLiquidity(positions_, poolAddress);
|
|
204
115
|
}
|
|
205
116
|
|
|
206
|
-
function
|
|
117
|
+
function buildConfig() internal view returns (CoinConfig memory coinConfig) {
|
|
207
118
|
coinConfig = CoinConfig({
|
|
208
119
|
protocolRewardRecipient: protocolRewardRecipient,
|
|
209
120
|
platformReferrer: platformReferrer,
|
|
210
|
-
currency: currency,
|
|
211
121
|
payoutRecipient: payoutRecipient,
|
|
212
|
-
protocolRewards: protocolRewards
|
|
213
|
-
poolConfiguration: poolConfiguration,
|
|
214
|
-
poolAddress: poolAddress,
|
|
215
|
-
uniswapV3Config: UniV3Config({weth: WETH, v3Factory: v3Factory, swapRouter: swapRouter, airlock: airlock})
|
|
122
|
+
protocolRewards: protocolRewards
|
|
216
123
|
});
|
|
217
124
|
}
|
|
218
125
|
|
|
126
|
+
function getPoolConfiguration() public view returns (PoolConfiguration memory) {
|
|
127
|
+
return poolConfiguration;
|
|
128
|
+
}
|
|
129
|
+
|
|
219
130
|
/// @notice Executes a buy order
|
|
220
131
|
/// @param recipient The recipient address of the coins
|
|
221
132
|
/// @param orderSize The amount of coins to buy
|
|
@@ -228,7 +139,24 @@ contract Coin is ICoin, ContractVersionBase, ERC20PermitUpgradeable, MultiOwnabl
|
|
|
228
139
|
uint160 sqrtPriceLimitX96,
|
|
229
140
|
address tradeReferrer
|
|
230
141
|
) public payable nonReentrant returns (uint256, uint256) {
|
|
231
|
-
|
|
142
|
+
CoinConfig memory coinConfig = buildConfig();
|
|
143
|
+
(uint256 amountOut, uint256 tradeReward, uint256 trueOrderSize) = UniV3BuySell.handleBuy(
|
|
144
|
+
recipient,
|
|
145
|
+
orderSize,
|
|
146
|
+
minAmountOut,
|
|
147
|
+
sqrtPriceLimitX96,
|
|
148
|
+
tradeReferrer,
|
|
149
|
+
coinConfig,
|
|
150
|
+
currency,
|
|
151
|
+
ISwapRouter(swapRouter),
|
|
152
|
+
IWETH(WETH)
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
UniV3BuySell.handleMarketRewards(coinConfig, currency, poolAddress, positions, IWETH(WETH), dopplerFeeRecipient());
|
|
156
|
+
|
|
157
|
+
emit CoinBuy(msg.sender, recipient, tradeReferrer, amountOut, currency, tradeReward, trueOrderSize);
|
|
158
|
+
|
|
159
|
+
return (orderSize, amountOut);
|
|
232
160
|
}
|
|
233
161
|
|
|
234
162
|
/// @notice Executes a sell order
|
|
@@ -253,21 +181,33 @@ contract Coin is ICoin, ContractVersionBase, ERC20PermitUpgradeable, MultiOwnabl
|
|
|
253
181
|
// Approve the Uniswap V3 swap router
|
|
254
182
|
this.approve(swapRouter, orderSize);
|
|
255
183
|
|
|
256
|
-
|
|
257
|
-
|
|
184
|
+
CoinConfig memory coinConfig = buildConfig();
|
|
185
|
+
|
|
186
|
+
SellResult memory result = UniV3BuySell.handleSell(
|
|
187
|
+
recipient,
|
|
188
|
+
beforeCoinBalance,
|
|
189
|
+
orderSize,
|
|
190
|
+
minAmountOut,
|
|
191
|
+
sqrtPriceLimitX96,
|
|
192
|
+
tradeReferrer,
|
|
193
|
+
coinConfig,
|
|
194
|
+
currency,
|
|
195
|
+
ISwapRouter(swapRouter),
|
|
196
|
+
IWETH(WETH)
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
UniV3BuySell.handleMarketRewards(coinConfig, currency, poolAddress, positions, IWETH(WETH), dopplerFeeRecipient());
|
|
200
|
+
|
|
201
|
+
emit ICoin.CoinSell(msg.sender, recipient, tradeReferrer, result.trueOrderSize, currency, result.tradeReward, result.payoutSize);
|
|
258
202
|
|
|
259
|
-
|
|
260
|
-
/// @param amount The amount of tokens to burn
|
|
261
|
-
function burn(uint256 amount) external {
|
|
262
|
-
// This burn function sets the from as msg.sender, so having an unauthed call is safe.
|
|
263
|
-
_burn(msg.sender, amount);
|
|
203
|
+
return (result.trueOrderSize, result.payoutSize);
|
|
264
204
|
}
|
|
265
205
|
|
|
266
206
|
/// @notice Force claim any accrued secondary rewards from the market's liquidity position.
|
|
267
207
|
/// @dev This function is a fallback, secondary rewards will be claimed automatically on each buy and sell.
|
|
268
208
|
/// @param pushEthRewards Whether to push the ETH directly to the recipients.
|
|
269
209
|
function claimSecondaryRewards(bool pushEthRewards) external nonReentrant {
|
|
270
|
-
MarketRewards memory rewards = UniV3BuySell.handleMarketRewards(
|
|
210
|
+
MarketRewards memory rewards = UniV3BuySell.handleMarketRewards(buildConfig(), currency, poolAddress, positions, IWETH(WETH), dopplerFeeRecipient());
|
|
271
211
|
|
|
272
212
|
if (pushEthRewards && rewards.totalAmountCurrency > 0 && currency == WETH) {
|
|
273
213
|
IProtocolRewards(protocolRewards).withdrawFor(payoutRecipient, rewards.creatorPayoutAmountCurrency);
|
|
@@ -276,38 +216,6 @@ contract Coin is ICoin, ContractVersionBase, ERC20PermitUpgradeable, MultiOwnabl
|
|
|
276
216
|
}
|
|
277
217
|
}
|
|
278
218
|
|
|
279
|
-
/// @notice Set the creator's payout address
|
|
280
|
-
/// @param newPayoutRecipient The new recipient address
|
|
281
|
-
function setPayoutRecipient(address newPayoutRecipient) external onlyOwner {
|
|
282
|
-
_setPayoutRecipient(newPayoutRecipient);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/// @notice Set the contract URI
|
|
286
|
-
/// @param newURI The new URI
|
|
287
|
-
function setContractURI(string memory newURI) external onlyOwner {
|
|
288
|
-
_setContractURI(newURI);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/// @notice The contract metadata
|
|
292
|
-
function contractURI() external view returns (string memory) {
|
|
293
|
-
return tokenURI;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/// @notice ERC165 interface support
|
|
297
|
-
/// @param interfaceId The interface ID to check
|
|
298
|
-
function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {
|
|
299
|
-
return
|
|
300
|
-
interfaceId == type(ICoin).interfaceId ||
|
|
301
|
-
interfaceId == type(ICoinComments).interfaceId ||
|
|
302
|
-
interfaceId == type(IERC7572).interfaceId ||
|
|
303
|
-
interfaceId == type(IERC165).interfaceId;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/// @notice Receives ETH converted from WETH
|
|
307
|
-
receive() external payable {
|
|
308
|
-
require(msg.sender == WETH, OnlyWeth());
|
|
309
|
-
}
|
|
310
|
-
|
|
311
219
|
/// @dev Called by the pool after minting liquidity to transfer the associated coins
|
|
312
220
|
function uniswapV3MintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata) external {
|
|
313
221
|
if (msg.sender != poolAddress) revert OnlyPool(msg.sender, poolAddress);
|
|
@@ -315,31 +223,8 @@ contract Coin is ICoin, ContractVersionBase, ERC20PermitUpgradeable, MultiOwnabl
|
|
|
315
223
|
IERC20(address(this)).safeTransfer(poolAddress, amount0Owed == 0 ? amount1Owed : amount0Owed);
|
|
316
224
|
}
|
|
317
225
|
|
|
318
|
-
/// @
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
emit CoinTransfer(from, to, value, balanceOf(from), balanceOf(to));
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/// @dev Used to set the payout recipient on coin creation and updates
|
|
326
|
-
/// @param newPayoutRecipient The new recipient address
|
|
327
|
-
function _setPayoutRecipient(address newPayoutRecipient) internal {
|
|
328
|
-
if (newPayoutRecipient == address(0)) {
|
|
329
|
-
revert AddressZero();
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
emit CoinPayoutRecipientUpdated(msg.sender, payoutRecipient, newPayoutRecipient);
|
|
333
|
-
|
|
334
|
-
payoutRecipient = newPayoutRecipient;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/// @dev Used to set the contract URI on coin creation and updates
|
|
338
|
-
/// @param newURI The new URI
|
|
339
|
-
function _setContractURI(string memory newURI) internal {
|
|
340
|
-
emit ContractMetadataUpdated(msg.sender, newURI, name());
|
|
341
|
-
emit ContractURIUpdated();
|
|
342
|
-
|
|
343
|
-
tokenURI = newURI;
|
|
226
|
+
/// @notice Receives ETH converted from WETH
|
|
227
|
+
receive() external payable {
|
|
228
|
+
require(msg.sender == WETH, OnlyWeth());
|
|
344
229
|
}
|
|
345
230
|
}
|
package/src/CoinV4.sol
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
import {IPoolManager, PoolKey, Currency, IHooks} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
|
|
5
|
+
|
|
6
|
+
import {BaseCoin} from "./BaseCoin.sol";
|
|
7
|
+
import {ICoinV4, IHasPoolKey, IHasSwapPath} from "./interfaces/ICoinV4.sol";
|
|
8
|
+
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
9
|
+
import {PoolConfiguration} from "./types/PoolConfiguration.sol";
|
|
10
|
+
import {UniV4SwapToCurrency} from "./libs/UniV4SwapToCurrency.sol";
|
|
11
|
+
import {PathKey} from "@uniswap/v4-periphery/src/libraries/PathKey.sol";
|
|
12
|
+
import {IDeployedCoinVersionLookup} from "./interfaces/IDeployedCoinVersionLookup.sol";
|
|
13
|
+
|
|
14
|
+
contract CoinV4 is BaseCoin, ICoinV4 {
|
|
15
|
+
/// @notice The Uniswap v4 pool manager singleton contract reference.
|
|
16
|
+
IPoolManager public immutable poolManager;
|
|
17
|
+
|
|
18
|
+
/// @notice The hooks contract used by this coin.
|
|
19
|
+
IHooks public immutable hooks;
|
|
20
|
+
|
|
21
|
+
/// @notice The pool key for the coin. Type from Uniswap V4 core.
|
|
22
|
+
PoolKey private poolKey;
|
|
23
|
+
|
|
24
|
+
/// @notice The configuration for the pool.
|
|
25
|
+
PoolConfiguration private poolConfiguration;
|
|
26
|
+
|
|
27
|
+
/// @notice The constructor for the static CoinV4 contract deployment shared across all Coins.
|
|
28
|
+
/// @dev All arguments are required and cannot be set to teh 0 address.
|
|
29
|
+
/// @param protocolRewardRecipient_ The address of the protocol reward recipient
|
|
30
|
+
/// @param protocolRewards_ The address of the protocol rewards contract
|
|
31
|
+
/// @param poolManager_ The address of the pool manager
|
|
32
|
+
/// @param airlock_ The address of the Airlock contract, ownership is used for a protocol fee split.
|
|
33
|
+
/// @param hooks_ The address of the hooks contract
|
|
34
|
+
/// @notice Returns the pool key for the coin
|
|
35
|
+
constructor(
|
|
36
|
+
address protocolRewardRecipient_,
|
|
37
|
+
address protocolRewards_,
|
|
38
|
+
IPoolManager poolManager_,
|
|
39
|
+
address airlock_,
|
|
40
|
+
IHooks hooks_
|
|
41
|
+
) BaseCoin(protocolRewardRecipient_, protocolRewards_, airlock_) {
|
|
42
|
+
if (address(poolManager_) == address(0)) {
|
|
43
|
+
revert AddressZero();
|
|
44
|
+
}
|
|
45
|
+
if (address(hooks_) == address(0)) {
|
|
46
|
+
revert AddressZero();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
poolManager = poolManager_;
|
|
50
|
+
hooks = hooks_;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// @inheritdoc IHasPoolKey
|
|
54
|
+
function getPoolKey() public view returns (PoolKey memory) {
|
|
55
|
+
return poolKey;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// @inheritdoc ICoinV4
|
|
59
|
+
function getPoolConfiguration() public view returns (PoolConfiguration memory) {
|
|
60
|
+
return poolConfiguration;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// @inheritdoc ICoinV4
|
|
64
|
+
function initialize(
|
|
65
|
+
address payoutRecipient_,
|
|
66
|
+
address[] memory owners_,
|
|
67
|
+
string memory tokenURI_,
|
|
68
|
+
string memory name_,
|
|
69
|
+
string memory symbol_,
|
|
70
|
+
address platformReferrer_,
|
|
71
|
+
address currency_,
|
|
72
|
+
PoolKey memory poolKey_,
|
|
73
|
+
uint160 sqrtPriceX96,
|
|
74
|
+
PoolConfiguration memory poolConfiguration_
|
|
75
|
+
) public initializer {
|
|
76
|
+
super._initialize(payoutRecipient_, owners_, tokenURI_, name_, symbol_, platformReferrer_);
|
|
77
|
+
|
|
78
|
+
currency = currency_;
|
|
79
|
+
poolKey = poolKey_;
|
|
80
|
+
poolConfiguration = poolConfiguration_;
|
|
81
|
+
|
|
82
|
+
// transfer the supply to the hook
|
|
83
|
+
_transfer(address(this), address(hooks), balanceOf(address(this)));
|
|
84
|
+
// initialize the pool - the hook will mint its positions in the afterInitialize callback
|
|
85
|
+
poolManager.initialize(poolKey, sqrtPriceX96);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function supportsInterface(bytes4 interfaceId) public pure virtual override(BaseCoin, IERC165) returns (bool) {
|
|
89
|
+
return interfaceId == type(IHasPoolKey).interfaceId || type(IHasSwapPath).interfaceId == interfaceId || super.supportsInterface(interfaceId);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// @inheritdoc IHasSwapPath
|
|
93
|
+
function getPayoutSwapPath(IDeployedCoinVersionLookup coinVersionLookup) external view returns (IHasSwapPath.PayoutSwapPath memory payoutSwapPath) {
|
|
94
|
+
// if to swap in is this currency,
|
|
95
|
+
// if backing currency is a coin, then recursively get the path from the coin
|
|
96
|
+
payoutSwapPath.currencyIn = Currency.wrap(address(this));
|
|
97
|
+
|
|
98
|
+
// swap to backing currency
|
|
99
|
+
PathKey memory thisPathKey = PathKey({
|
|
100
|
+
intermediateCurrency: Currency.wrap(currency),
|
|
101
|
+
fee: poolKey.fee,
|
|
102
|
+
tickSpacing: poolKey.tickSpacing,
|
|
103
|
+
hooks: poolKey.hooks,
|
|
104
|
+
hookData: ""
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// get backing currency swap path - if the backing currency is a v4 coin and has a swap path.
|
|
108
|
+
PathKey[] memory subPath = UniV4SwapToCurrency.getSubSwapPath(currency, coinVersionLookup);
|
|
109
|
+
|
|
110
|
+
if (subPath.length > 0) {
|
|
111
|
+
payoutSwapPath.path = new PathKey[](1 + subPath.length);
|
|
112
|
+
payoutSwapPath.path[0] = thisPathKey;
|
|
113
|
+
for (uint256 i = 0; i < subPath.length; i++) {
|
|
114
|
+
payoutSwapPath.path[i + 1] = subPath[i];
|
|
115
|
+
}
|
|
116
|
+
} else {
|
|
117
|
+
payoutSwapPath.path = new PathKey[](1);
|
|
118
|
+
payoutSwapPath.path[0] = thisPathKey;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|