@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.
- package/.turbo/turbo-build.log +131 -114
- package/CHANGELOG.md +40 -0
- package/abis/BaseCoin.json +26 -118
- package/abis/BaseTest.json +47 -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 +1053 -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 +1528 -0
- package/abis/HooksDeployment.json +23 -0
- package/abis/HooksTest.json +47 -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 +191 -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 +67 -0
- package/abis/Vm.json +1482 -111
- package/abis/VmSafe.json +856 -32
- package/abis/ZoraFactoryImpl.json +339 -1
- package/abis/ZoraV4CoinHook.json +455 -5
- package/addresses/8453.json +8 -4
- package/addresses/84532.json +8 -4
- package/dist/index.cjs +1920 -169
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1916 -169
- package/dist/index.js.map +1 -1
- package/dist/wagmiGenerated.d.ts +2599 -183
- package/dist/wagmiGenerated.d.ts.map +1 -1
- package/package/wagmiGenerated.ts +1928 -165
- package/package.json +8 -3
- package/remappings.txt +6 -1
- package/script/CoinsDeployerBase.sol +74 -11
- package/script/DeployDevFactory.s.sol +21 -0
- package/script/PrintUpgradeCommand.s.sol +13 -0
- package/script/Simulate.s.sol +1 -10
- package/script/TestBackingCoinSwap.s.sol +146 -0
- package/script/TestV4Swap.s.sol +136 -0
- package/script/UpgradeFactoryImpl.s.sol +1 -1
- package/src/BaseCoin.sol +176 -0
- package/src/Coin.sol +87 -202
- package/src/CoinV4.sol +121 -0
- package/src/ZoraFactoryImpl.sol +208 -36
- package/src/hooks/ZoraV4CoinHook.sol +195 -0
- package/src/hooks/{BaseCoinDeployHook.sol → deployment/BaseCoinDeployHook.sol} +3 -3
- package/src/hooks/{BuySupplyWithSwapRouterHook.sol → deployment/BuySupplyWithSwapRouterHook.sol} +7 -5
- 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 +65 -27
- 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 +180 -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 +84 -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 +129 -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 +752 -0
- package/test/{Hooks.t.sol → DeploymentHooks.t.sol} +2 -6
- package/test/Factory.t.sol +80 -47
- package/test/MultiOwnable.t.sol +6 -3
- package/test/Upgrades.t.sol +6 -5
- package/test/mocks/MockERC20.sol +12 -0
- package/test/utils/BaseTest.sol +106 -56
- 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/libs/CoinLegacy.sol +0 -48
- package/src/libs/CoinLegacyMarket.sol +0 -182
package/src/BaseCoin.sol
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
5
|
+
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
6
|
+
import {ICoin, IHasRewardsRecipients} from "./interfaces/ICoin.sol";
|
|
7
|
+
import {ICoinComments} from "./interfaces/ICoinComments.sol";
|
|
8
|
+
import {IERC7572} from "./interfaces/IERC7572.sol";
|
|
9
|
+
import {IAirlock} from "./interfaces/IAirlock.sol";
|
|
10
|
+
|
|
11
|
+
import {ERC20PermitUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol";
|
|
12
|
+
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
|
|
13
|
+
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
14
|
+
import {ContractVersionBase} from "./version/ContractVersionBase.sol";
|
|
15
|
+
import {MultiOwnable} from "./utils/MultiOwnable.sol";
|
|
16
|
+
import {CoinConstants} from "./libs/CoinConstants.sol";
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
$$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\
|
|
20
|
+
$$ __$$\ $$ __$$\ \_$$ _|$$$\ $$ |
|
|
21
|
+
$$ / \__|$$ / $$ | $$ | $$$$\ $$ |
|
|
22
|
+
$$ | $$ | $$ | $$ | $$ $$\$$ |
|
|
23
|
+
$$ | $$ | $$ | $$ | $$ \$$$$ |
|
|
24
|
+
$$ | $$\ $$ | $$ | $$ | $$ |\$$$ |
|
|
25
|
+
\$$$$$$ | $$$$$$ |$$$$$$\ $$ | \$$ |
|
|
26
|
+
\______/ \______/ \______|\__| \__|
|
|
27
|
+
*/
|
|
28
|
+
abstract contract BaseCoin is ICoin, ContractVersionBase, ERC20PermitUpgradeable, MultiOwnable, ReentrancyGuardUpgradeable {
|
|
29
|
+
using SafeERC20 for IERC20;
|
|
30
|
+
|
|
31
|
+
/// @notice The address of the protocol rewards contract
|
|
32
|
+
address public immutable protocolRewards;
|
|
33
|
+
/// @notice The address of the protocol reward recipient
|
|
34
|
+
address public immutable protocolRewardRecipient;
|
|
35
|
+
/// @notice The address of the Airlock contract, ownership is used for a protocol fee split.
|
|
36
|
+
address public immutable airlock;
|
|
37
|
+
|
|
38
|
+
/// @notice The metadata URI
|
|
39
|
+
string public tokenURI;
|
|
40
|
+
/// @notice The address of the coin creator
|
|
41
|
+
address public payoutRecipient;
|
|
42
|
+
/// @notice The address of the platform referrer
|
|
43
|
+
address public platformReferrer;
|
|
44
|
+
/// @notice The address of the currency
|
|
45
|
+
address public currency;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @notice The constructor for the static Coin contract deployment shared across all Coins.
|
|
49
|
+
* @param _protocolRewardRecipient The address of the protocol reward recipient
|
|
50
|
+
* @param _protocolRewards The address of the protocol rewards contract
|
|
51
|
+
* @param _airlock The address of the Airlock contract
|
|
52
|
+
*/
|
|
53
|
+
constructor(address _protocolRewardRecipient, address _protocolRewards, address _airlock) initializer {
|
|
54
|
+
if (_protocolRewardRecipient == address(0)) {
|
|
55
|
+
revert AddressZero();
|
|
56
|
+
}
|
|
57
|
+
if (_protocolRewards == address(0)) {
|
|
58
|
+
revert AddressZero();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (_airlock == address(0)) {
|
|
62
|
+
revert AddressZero();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
protocolRewardRecipient = _protocolRewardRecipient;
|
|
66
|
+
protocolRewards = _protocolRewards;
|
|
67
|
+
airlock = _airlock;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/// @notice Initializes a new coin
|
|
71
|
+
/// @param payoutRecipient_ The address of the coin creator
|
|
72
|
+
/// @param tokenURI_ The metadata URI
|
|
73
|
+
/// @param name_ The coin name
|
|
74
|
+
/// @param symbol_ The coin symbol
|
|
75
|
+
/// @param platformReferrer_ The address of the platform referrer
|
|
76
|
+
function _initialize(
|
|
77
|
+
address payoutRecipient_,
|
|
78
|
+
address[] memory owners_,
|
|
79
|
+
string memory tokenURI_,
|
|
80
|
+
string memory name_,
|
|
81
|
+
string memory symbol_,
|
|
82
|
+
address platformReferrer_
|
|
83
|
+
) internal {
|
|
84
|
+
// Validate the creation parameters
|
|
85
|
+
if (payoutRecipient_ == address(0)) {
|
|
86
|
+
revert AddressZero();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Set base contract state
|
|
90
|
+
__ERC20_init(name_, symbol_);
|
|
91
|
+
__ERC20Permit_init(name_);
|
|
92
|
+
__MultiOwnable_init(owners_);
|
|
93
|
+
__ReentrancyGuard_init();
|
|
94
|
+
|
|
95
|
+
// Set mutable state
|
|
96
|
+
_setPayoutRecipient(payoutRecipient_);
|
|
97
|
+
_setContractURI(tokenURI_);
|
|
98
|
+
|
|
99
|
+
// Store the referrer or use the protocol reward recipient if not set
|
|
100
|
+
platformReferrer = platformReferrer_ == address(0) ? protocolRewardRecipient : platformReferrer_;
|
|
101
|
+
|
|
102
|
+
// Mint the total supply to the coin contract
|
|
103
|
+
_mint(address(this), CoinConstants.MAX_TOTAL_SUPPLY);
|
|
104
|
+
|
|
105
|
+
// Distribute the creator launch reward to the payout recipient
|
|
106
|
+
_transfer(address(this), payoutRecipient, CoinConstants.CREATOR_LAUNCH_REWARD);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// @notice Enables a user to burn their tokens
|
|
110
|
+
/// @param amount The amount of tokens to burn
|
|
111
|
+
function burn(uint256 amount) external {
|
|
112
|
+
// This burn function sets the from as msg.sender, so having an unauthed call is safe.
|
|
113
|
+
_burn(msg.sender, amount);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// @notice Set the creator's payout address
|
|
117
|
+
/// @param newPayoutRecipient The new recipient address
|
|
118
|
+
function setPayoutRecipient(address newPayoutRecipient) external onlyOwner {
|
|
119
|
+
_setPayoutRecipient(newPayoutRecipient);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/// @notice Set the contract URI
|
|
123
|
+
/// @param newURI The new URI
|
|
124
|
+
function setContractURI(string memory newURI) external onlyOwner {
|
|
125
|
+
_setContractURI(newURI);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/// @notice The contract metadata
|
|
129
|
+
function contractURI() external view returns (string memory) {
|
|
130
|
+
return tokenURI;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/// @notice ERC165 interface support
|
|
134
|
+
/// @param interfaceId The interface ID to check
|
|
135
|
+
function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {
|
|
136
|
+
return
|
|
137
|
+
interfaceId == type(ICoin).interfaceId ||
|
|
138
|
+
interfaceId == type(ICoinComments).interfaceId ||
|
|
139
|
+
interfaceId == type(IERC7572).interfaceId ||
|
|
140
|
+
interfaceId == type(IERC165).interfaceId ||
|
|
141
|
+
interfaceId == type(IHasRewardsRecipients).interfaceId;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/// @dev Overrides ERC20's _update function to emit a superset `CoinTransfer` event
|
|
145
|
+
function _update(address from, address to, uint256 value) internal virtual override {
|
|
146
|
+
super._update(from, to, value);
|
|
147
|
+
|
|
148
|
+
emit CoinTransfer(from, to, value, balanceOf(from), balanceOf(to));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/// @dev Used to set the payout recipient on coin creation and updates
|
|
152
|
+
/// @param newPayoutRecipient The new recipient address
|
|
153
|
+
function _setPayoutRecipient(address newPayoutRecipient) internal {
|
|
154
|
+
if (newPayoutRecipient == address(0)) {
|
|
155
|
+
revert AddressZero();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
emit CoinPayoutRecipientUpdated(msg.sender, payoutRecipient, newPayoutRecipient);
|
|
159
|
+
|
|
160
|
+
payoutRecipient = newPayoutRecipient;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/// @dev Used to set the contract URI on coin creation and updates
|
|
164
|
+
/// @param newURI The new URI
|
|
165
|
+
function _setContractURI(string memory newURI) internal {
|
|
166
|
+
emit ContractMetadataUpdated(msg.sender, newURI, name());
|
|
167
|
+
emit ContractURIUpdated();
|
|
168
|
+
|
|
169
|
+
tokenURI = newURI;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/// @notice Returns the address of the Doppler protocol fee recipient
|
|
173
|
+
function dopplerFeeRecipient() public view returns (address) {
|
|
174
|
+
return IAirlock(airlock).owner();
|
|
175
|
+
}
|
|
176
|
+
}
|
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
|
}
|