@zoralabs/coins 0.4.0 → 0.5.1-sdkalpha.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 (50) hide show
  1. package/.env.example +7 -0
  2. package/.turbo/turbo-build.log +93 -74
  3. package/CHANGELOG.md +12 -0
  4. package/README.md +29 -0
  5. package/abis/Coin.json +10 -0
  6. package/abis/CoinTest.json +55 -0
  7. package/abis/Create2.json +28 -0
  8. package/abis/DeployScript.json +9 -0
  9. package/abis/DeterministicDeployerAndCaller.json +315 -0
  10. package/abis/DeterministicUUPSProxyDeployer.json +167 -0
  11. package/abis/FactoryTest.json +20 -0
  12. package/abis/GenerateDeterministicParams.json +9 -0
  13. package/abis/ICoin.json +10 -0
  14. package/abis/IImmutableCreate2Factory.json +93 -0
  15. package/abis/ISafe.json +15 -0
  16. package/abis/ISymbol.json +15 -0
  17. package/abis/ImmutableCreate2FactoryUtils.json +15 -0
  18. package/abis/LibString.json +7 -0
  19. package/abis/ProxyShim.json +112 -0
  20. package/abis/ZoraFactory.json +0 -5
  21. package/addresses/8453.json +5 -8
  22. package/addresses/84532.json +5 -8
  23. package/deterministicConfig/deployerAndCaller.json +5 -0
  24. package/deterministicConfig/zoraFactory.json +8 -0
  25. package/dist/index.cjs +100 -4
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.js +96 -3
  28. package/dist/index.js.map +1 -1
  29. package/dist/wagmiGenerated.d.ts +475 -0
  30. package/dist/wagmiGenerated.d.ts.map +1 -1
  31. package/foundry.toml +14 -0
  32. package/integration/.env +2 -0
  33. package/lcov.info +634 -0
  34. package/package/wagmiGenerated.ts +111 -2
  35. package/package.json +4 -3
  36. package/remappings.txt +2 -1
  37. package/script/CoinsDeployerBase.sol +98 -0
  38. package/script/Deploy.s.sol +14 -5
  39. package/script/GenerateDeterministicParams.s.sol +43 -0
  40. package/src/Coin.sol +25 -7
  41. package/src/ZoraFactoryImpl.sol +2 -2
  42. package/src/interfaces/ICoin.sol +8 -2
  43. package/src/proxy/ZoraFactory.sol +7 -1
  44. package/src/version/ContractVersionBase.sol +1 -1
  45. package/test/Coin.t.sol +152 -4
  46. package/test/Factory.t.sol +33 -0
  47. package/test/utils/BaseTest.sol +4 -4
  48. package/wagmi.config.ts +7 -1
  49. package/abis/Deploy.json +0 -29
  50. package/addresses/1.json +0 -4
@@ -146,7 +146,10 @@ export const coinABI = [
146
146
  { name: 'tradeReferrer', internalType: 'address', type: 'address' },
147
147
  ],
148
148
  name: 'buy',
149
- outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
149
+ outputs: [
150
+ { name: '', internalType: 'uint256', type: 'uint256' },
151
+ { name: '', internalType: 'uint256', type: 'uint256' },
152
+ ],
150
153
  stateMutability: 'payable',
151
154
  },
152
155
  {
@@ -352,7 +355,10 @@ export const coinABI = [
352
355
  { name: 'tradeReferrer', internalType: 'address', type: 'address' },
353
356
  ],
354
357
  name: 'sell',
355
- outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
358
+ outputs: [
359
+ { name: '', internalType: 'uint256', type: 'uint256' },
360
+ { name: '', internalType: 'uint256', type: 'uint256' },
361
+ ],
356
362
  stateMutability: 'nonpayable',
357
363
  },
358
364
  {
@@ -948,10 +954,95 @@ export const coinABI = [
948
954
  { type: 'error', inputs: [], name: 'UseRevokeOwnershipToRemoveSelf' },
949
955
  ] as const
950
956
 
957
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
958
+ // IUniswapV3Pool
959
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
960
+
961
+ export const iUniswapV3PoolABI = [
962
+ {
963
+ type: 'function',
964
+ inputs: [],
965
+ name: 'feeGrowthGlobal0X128',
966
+ outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
967
+ stateMutability: 'view',
968
+ },
969
+ {
970
+ type: 'function',
971
+ inputs: [],
972
+ name: 'feeGrowthGlobal1X128',
973
+ outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
974
+ stateMutability: 'view',
975
+ },
976
+ {
977
+ type: 'function',
978
+ inputs: [],
979
+ name: 'slot0',
980
+ outputs: [
981
+ {
982
+ name: 'slot0',
983
+ internalType: 'struct IUniswapV3Pool.Slot0',
984
+ type: 'tuple',
985
+ components: [
986
+ { name: 'sqrtPriceX96', internalType: 'uint160', type: 'uint160' },
987
+ { name: 'tick', internalType: 'int24', type: 'int24' },
988
+ { name: 'observationIndex', internalType: 'uint16', type: 'uint16' },
989
+ {
990
+ name: 'observationCardinality',
991
+ internalType: 'uint16',
992
+ type: 'uint16',
993
+ },
994
+ {
995
+ name: 'observationCardinalityNext',
996
+ internalType: 'uint16',
997
+ type: 'uint16',
998
+ },
999
+ { name: 'feeProtocol', internalType: 'uint8', type: 'uint8' },
1000
+ { name: 'unlocked', internalType: 'bool', type: 'bool' },
1001
+ ],
1002
+ },
1003
+ ],
1004
+ stateMutability: 'view',
1005
+ },
1006
+ {
1007
+ type: 'function',
1008
+ inputs: [
1009
+ { name: 'recipient', internalType: 'address', type: 'address' },
1010
+ { name: 'zeroForOne', internalType: 'bool', type: 'bool' },
1011
+ { name: 'amountSpecified', internalType: 'int256', type: 'int256' },
1012
+ { name: 'sqrtPriceLimitX96', internalType: 'uint160', type: 'uint160' },
1013
+ { name: 'data', internalType: 'bytes', type: 'bytes' },
1014
+ ],
1015
+ name: 'swap',
1016
+ outputs: [
1017
+ { name: 'amount0', internalType: 'int256', type: 'int256' },
1018
+ { name: 'amount1', internalType: 'int256', type: 'int256' },
1019
+ ],
1020
+ stateMutability: 'nonpayable',
1021
+ },
1022
+ {
1023
+ type: 'function',
1024
+ inputs: [],
1025
+ name: 'token0',
1026
+ outputs: [{ name: '', internalType: 'address', type: 'address' }],
1027
+ stateMutability: 'nonpayable',
1028
+ },
1029
+ {
1030
+ type: 'function',
1031
+ inputs: [],
1032
+ name: 'token1',
1033
+ outputs: [{ name: '', internalType: 'address', type: 'address' }],
1034
+ stateMutability: 'nonpayable',
1035
+ },
1036
+ ] as const
1037
+
951
1038
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
952
1039
  // ZoraFactoryImpl
953
1040
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
954
1041
 
1042
+ /**
1043
+ * - [__View Contract on Base Basescan__](https://basescan.org/address/0x777777751622c0d3258f214F9DF38E35BF45baF3)
1044
+ * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0x777777751622c0d3258f214F9DF38E35BF45baF3)
1045
+ */
955
1046
  export const zoraFactoryImplABI = [
956
1047
  {
957
1048
  type: 'constructor',
@@ -1195,3 +1286,21 @@ export const zoraFactoryImplABI = [
1195
1286
  name: 'UUPSUnsupportedProxiableUUID',
1196
1287
  },
1197
1288
  ] as const
1289
+
1290
+ /**
1291
+ * - [__View Contract on Base Basescan__](https://basescan.org/address/0x777777751622c0d3258f214F9DF38E35BF45baF3)
1292
+ * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0x777777751622c0d3258f214F9DF38E35BF45baF3)
1293
+ */
1294
+ export const zoraFactoryImplAddress = {
1295
+ 8453: '0x777777751622c0d3258f214F9DF38E35BF45baF3',
1296
+ 84532: '0x777777751622c0d3258f214F9DF38E35BF45baF3',
1297
+ } as const
1298
+
1299
+ /**
1300
+ * - [__View Contract on Base Basescan__](https://basescan.org/address/0x777777751622c0d3258f214F9DF38E35BF45baF3)
1301
+ * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0x777777751622c0d3258f214F9DF38E35BF45baF3)
1302
+ */
1303
+ export const zoraFactoryImplConfig = {
1304
+ address: zoraFactoryImplAddress,
1305
+ abi: zoraFactoryImplABI,
1306
+ } as const
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zoralabs/coins",
3
- "version": "0.4.0",
3
+ "version": "0.5.1-sdkalpha.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -25,13 +25,14 @@
25
25
  "forge-std": "https://github.com/foundry-rs/forge-std#v1.9.1",
26
26
  "prettier": "^3.0.3",
27
27
  "prettier-plugin-solidity": "^1.4.1",
28
+ "solady": "0.0.132",
28
29
  "tsup": "^7.2.0",
29
30
  "tsx": "^3.13.0",
30
31
  "typescript": "^5.2.2",
31
32
  "viem": "^2.21.18",
32
- "@zoralabs/shared-contracts": "^0.0.1",
33
+ "@zoralabs/tsconfig": "^0.0.1",
33
34
  "@zoralabs/shared-scripts": "^0.0.0",
34
- "@zoralabs/tsconfig": "^0.0.1"
35
+ "@zoralabs/shared-contracts": "^0.0.1"
35
36
  },
36
37
  "scripts": {
37
38
  "build": "pnpm run wagmi:generate && pnpm run copy-abis && pnpm run prettier:write && tsup",
package/remappings.txt CHANGED
@@ -1,4 +1,5 @@
1
1
  ds-test/=node_modules/ds-test/src/
2
2
  forge-std/=node_modules/forge-std/src/
3
3
  @openzeppelin/=node_modules/@openzeppelin/
4
- @zoralabs/shared-contracts/=node_modules/@zoralabs/shared-contracts/src/
4
+ @zoralabs/shared-contracts/=node_modules/@zoralabs/shared-contracts/src/
5
+ solady/=node_modules/solady/src/
@@ -0,0 +1,98 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.28;
3
+
4
+ import "forge-std/Script.sol";
5
+
6
+ import {ProxyDeployerScript, DeterministicContractConfig, DeterministicDeployerAndCaller} from "@zoralabs/shared-contracts/deployment/ProxyDeployerScript.sol";
7
+ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
8
+ import {ZoraFactoryImpl} from "../src/ZoraFactoryImpl.sol";
9
+ import {Coin} from "../src/Coin.sol";
10
+ import {IVersionedContract} from "@zoralabs/shared-contracts/interfaces/IVersionedContract.sol";
11
+
12
+ contract CoinsDeployerBase is ProxyDeployerScript {
13
+ address internal constant PROTOCOL_REWARDS = 0x7777777F279eba3d3Ad8F4E708545291A6fDBA8B;
14
+
15
+ using stdJson for string;
16
+
17
+ struct CoinsDeployment {
18
+ // Factory
19
+ address zoraFactory;
20
+ address zoraFactoryImpl;
21
+ // Implementation
22
+ address coinImpl;
23
+ string coinVersion;
24
+ }
25
+
26
+ function addressesFile() internal view returns (string memory) {
27
+ return string.concat("./addresses/", vm.toString(block.chainid), ".json");
28
+ }
29
+
30
+ function saveDeployment(CoinsDeployment memory deployment) internal {
31
+ string memory objectKey = "config";
32
+
33
+ vm.serializeAddress(objectKey, "ZORA_FACTORY", deployment.zoraFactory);
34
+ vm.serializeAddress(objectKey, "ZORA_FACTORY_IMPL", deployment.zoraFactoryImpl);
35
+ vm.serializeString(objectKey, "COIN_VERSION", deployment.coinVersion);
36
+ string memory result = vm.serializeAddress(objectKey, "COIN_IMPL", deployment.coinImpl);
37
+
38
+ vm.writeJson(result, addressesFile());
39
+ }
40
+
41
+ function readDeployment() internal returns (CoinsDeployment memory deployment) {
42
+ string memory file = addressesFile();
43
+ if (!vm.exists(file)) {
44
+ return deployment;
45
+ }
46
+ string memory json = vm.readFile(file);
47
+
48
+ deployment.zoraFactory = readAddressOrDefaultToZero(json, "ZORA_FACTORY");
49
+ deployment.zoraFactoryImpl = readAddressOrDefaultToZero(json, "ZORA_FACTORY_IMPL");
50
+ deployment.coinImpl = readAddressOrDefaultToZero(json, "COIN_IMPL");
51
+ deployment.coinVersion = readStringOrDefaultToEmpty(json, "COIN_VERSION");
52
+ }
53
+
54
+ function deployCoinImpl() internal returns (Coin) {
55
+ return new Coin(getZoraRecipient(), PROTOCOL_REWARDS, getWeth(), getNonFungiblePositionManager(), getUniswapSwapRouter());
56
+ }
57
+
58
+ function deployZoraFactoryImpl(address coinImpl) internal returns (ZoraFactoryImpl) {
59
+ return new ZoraFactoryImpl(coinImpl);
60
+ }
61
+
62
+ function deployZoraDeterministic(CoinsDeployment memory deployment, DeterministicDeployerAndCaller deployer) internal {
63
+ // read previously saved deterministic config
64
+ DeterministicContractConfig memory zoraConfig = readDeterministicContractConfig("zoraFactory");
65
+
66
+ // Deploy implementation contracts
67
+ deployment.coinImpl = address(deployCoinImpl());
68
+ deployment.zoraFactoryImpl = address(deployZoraFactoryImpl(deployment.coinImpl));
69
+ deployment.coinVersion = IVersionedContract(deployment.coinImpl).contractVersion();
70
+
71
+ if (deployment.zoraFactoryImpl.code.length == 0) {
72
+ revert("Factory Impl not yet deployed. Make sure to deploy it with DeployImpl.s.sol");
73
+ }
74
+
75
+ // build upgrade to and call for factory, with init call
76
+ bytes memory upgradeToAndCall = abi.encodeWithSelector(
77
+ UUPSUpgradeable.upgradeToAndCall.selector,
78
+ deployment.zoraFactoryImpl,
79
+ abi.encodeWithSelector(ZoraFactoryImpl.initialize.selector, getProxyAdmin())
80
+ );
81
+
82
+ // sign deployment with turnkey account
83
+ bytes memory signature = signDeploymentWithTurnkey(zoraConfig, upgradeToAndCall, deployer);
84
+
85
+ printVerificationCommand(zoraConfig);
86
+
87
+ deployment.zoraFactory = deployer.permitSafeCreate2AndCall(
88
+ signature,
89
+ zoraConfig.salt,
90
+ zoraConfig.creationCode,
91
+ upgradeToAndCall,
92
+ zoraConfig.deployedAddress
93
+ );
94
+
95
+ // validate that the zora factory owner is the proxy admin
96
+ require(ZoraFactoryImpl(deployment.zoraFactory).owner() == getProxyAdmin(), "Zora factory owner is not the proxy admin");
97
+ }
98
+ }
@@ -1,14 +1,23 @@
1
1
  // SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.13;
2
+ pragma solidity ^0.8.28;
3
3
 
4
- import {Script, console} from "forge-std/Script.sol";
5
-
6
- contract Deploy is Script {
7
- function setUp() public {}
4
+ import {ProxyDeployerScript, DeterministicDeployerAndCaller} from "@zoralabs/shared-contracts/deployment/ProxyDeployerScript.sol";
5
+ import {CoinsDeployerBase} from "./CoinsDeployerBase.sol";
8
6
 
7
+ contract DeployScript is CoinsDeployerBase {
9
8
  function run() public {
9
+ CoinsDeployment memory deployment = readDeployment();
10
+
10
11
  vm.startBroadcast();
11
12
 
13
+ // get deployer contract
14
+ DeterministicDeployerAndCaller deployer = createOrGetDeployerAndCaller();
15
+
16
+ deployZoraDeterministic(deployment, deployer);
17
+
12
18
  vm.stopBroadcast();
19
+
20
+ // save the deployment json
21
+ saveDeployment(deployment);
13
22
  }
14
23
  }
@@ -0,0 +1,43 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.28;
3
+
4
+ import "forge-std/Script.sol";
5
+
6
+ import {ImmutableCreate2FactoryUtils} from "@zoralabs/shared-contracts/utils/ImmutableCreate2FactoryUtils.sol";
7
+ import {ProxyDeployerScript, DeterministicDeployerAndCaller, DeterministicContractConfig} from "@zoralabs/shared-contracts/deployment/ProxyDeployerScript.sol";
8
+ import {ZoraFactory} from "../src/proxy/ZoraFactory.sol";
9
+
10
+ contract GenerateDeterministicParams is ProxyDeployerScript {
11
+ function mineForZoraAddress(DeterministicDeployerAndCaller deployer, address caller) private returns (DeterministicContractConfig memory config) {
12
+ // get proxy creation code
13
+ bytes memory initCode = deployer.proxyCreationCode(type(ZoraFactory).creationCode);
14
+ bytes32 initCodeHash = keccak256(initCode);
15
+
16
+ // uupsProxyDeployer is deployer
17
+ (bytes32 salt, address expectedAddress) = mineSalt(address(deployer), initCodeHash, "7777777", caller);
18
+
19
+ console2.log("salt");
20
+ console2.log(vm.toString(salt));
21
+
22
+ config.salt = salt;
23
+ config.deployedAddress = expectedAddress;
24
+ config.creationCode = initCode;
25
+ config.constructorArgs = deployer.proxyConstructorArgs();
26
+ config.contractName = "Zora";
27
+ config.deploymentCaller = caller;
28
+ }
29
+
30
+ function run() public {
31
+ address caller = vm.envAddress("DEPLOYER");
32
+
33
+ vm.startBroadcast();
34
+
35
+ // create a proxy deployer, which we can use to generate deterministic addresses and corresponding params
36
+ DeterministicDeployerAndCaller deployer = createOrGetDeployerAndCaller();
37
+
38
+ vm.stopBroadcast();
39
+
40
+ DeterministicContractConfig memory zoraConfig = mineForZoraAddress(deployer, caller);
41
+ saveDeterministicContractConfig(zoraConfig, "zoraFactory");
42
+ }
43
+ }
package/src/Coin.sol CHANGED
@@ -138,7 +138,7 @@ contract Coin is ICoin, CoinConstants, ContractVersionBase, ERC20PermitUpgradeab
138
138
  uint256 minAmountOut,
139
139
  uint160 sqrtPriceLimitX96,
140
140
  address tradeReferrer
141
- ) public payable nonReentrant returns (uint256) {
141
+ ) public payable nonReentrant returns (uint256, uint256) {
142
142
  // Ensure the recipient is not the zero address
143
143
  if (recipient == address(0)) {
144
144
  revert AddressZero();
@@ -173,7 +173,7 @@ contract Coin is ICoin, CoinConstants, ContractVersionBase, ERC20PermitUpgradeab
173
173
 
174
174
  emit CoinBuy(msg.sender, recipient, tradeReferrer, amountOut, currency, tradeReward, trueOrderSize);
175
175
 
176
- return amountOut;
176
+ return (orderSize, amountOut);
177
177
  }
178
178
 
179
179
  /// @notice Executes a sell order
@@ -188,12 +188,15 @@ contract Coin is ICoin, CoinConstants, ContractVersionBase, ERC20PermitUpgradeab
188
188
  uint256 minAmountOut,
189
189
  uint160 sqrtPriceLimitX96,
190
190
  address tradeReferrer
191
- ) public nonReentrant returns (uint256) {
191
+ ) public nonReentrant returns (uint256, uint256) {
192
192
  // Ensure the recipient is not the zero address
193
193
  if (recipient == address(0)) {
194
194
  revert AddressZero();
195
195
  }
196
196
 
197
+ // Record the coin balance of this contract before the swap
198
+ uint256 beforeCoinBalance = balanceOf(address(this));
199
+
197
200
  // Transfer the coins from the seller to this contract
198
201
  transfer(address(this), orderSize);
199
202
 
@@ -214,6 +217,21 @@ contract Coin is ICoin, CoinConstants, ContractVersionBase, ERC20PermitUpgradeab
214
217
  // Execute the swap
215
218
  uint256 amountOut = ISwapRouter(swapRouter).exactInputSingle(params);
216
219
 
220
+ // Record the coin balance of this contract after the swap
221
+ uint256 afterCoinBalance = balanceOf(address(this));
222
+
223
+ // If the swap was partially executed:
224
+ if (afterCoinBalance > beforeCoinBalance) {
225
+ // Calculate the refund
226
+ uint256 coinRefund = afterCoinBalance - beforeCoinBalance;
227
+
228
+ // Update the order size
229
+ orderSize -= coinRefund;
230
+
231
+ // Transfer the refund back to the seller
232
+ _transfer(address(this), recipient, coinRefund);
233
+ }
234
+
217
235
  // If currency is WETH, convert to ETH
218
236
  if (currency == WETH) {
219
237
  IWETH(WETH).withdraw(amountOut);
@@ -225,7 +243,7 @@ contract Coin is ICoin, CoinConstants, ContractVersionBase, ERC20PermitUpgradeab
225
243
  // Calculate the payout after the fee
226
244
  uint256 payoutSize = amountOut - tradeReward;
227
245
 
228
- _handleSellPayout(payoutSize, recipient);
246
+ _handlePayout(payoutSize, recipient);
229
247
 
230
248
  _handleTradeRewards(tradeReward, tradeReferrer);
231
249
 
@@ -233,7 +251,7 @@ contract Coin is ICoin, CoinConstants, ContractVersionBase, ERC20PermitUpgradeab
233
251
 
234
252
  emit CoinSell(msg.sender, recipient, tradeReferrer, orderSize, currency, tradeReward, payoutSize);
235
253
 
236
- return amountOut;
254
+ return (orderSize, payoutSize);
237
255
  }
238
256
 
239
257
  /// @notice Enables a user to burn their tokens
@@ -415,10 +433,10 @@ contract Coin is ICoin, CoinConstants, ContractVersionBase, ERC20PermitUpgradeab
415
433
  }
416
434
  }
417
435
 
418
- /// @dev Handles sending ETH and ERC20 payouts from sell orders to recipients
436
+ /// @dev Handles sending ETH and ERC20 payouts and refunds to recipients
419
437
  /// @param orderPayout The amount of currency to pay out
420
438
  /// @param recipient The address to receive the payout
421
- function _handleSellPayout(uint256 orderPayout, address recipient) internal {
439
+ function _handlePayout(uint256 orderPayout, address recipient) internal {
422
440
  if (currency == WETH) {
423
441
  Address.sendValue(payable(recipient), orderPayout);
424
442
  } else {
@@ -102,9 +102,9 @@ contract ZoraFactoryImpl is IZoraFactory, UUPSUpgradeable, ReentrancyGuardUpgrad
102
102
 
103
103
  IERC20(currency).approve(address(coin), orderSize);
104
104
 
105
- coinsPurchased = coin.buy(payoutRecipient, orderSize, 0, 0, address(0));
105
+ (, coinsPurchased) = coin.buy(payoutRecipient, orderSize, 0, 0, address(0));
106
106
  } else {
107
- coinsPurchased = coin.buy{value: msg.value}(payoutRecipient, orderSize, 0, 0, address(0));
107
+ (, coinsPurchased) = coin.buy{value: msg.value}(payoutRecipient, orderSize, 0, 0, address(0));
108
108
  }
109
109
  }
110
110
  }
@@ -172,7 +172,7 @@ interface ICoin is IERC165, IERC721Receiver, IERC7572 {
172
172
  uint256 minAmountOut,
173
173
  uint160 sqrtPriceLimitX96,
174
174
  address tradeReferrer
175
- ) external payable returns (uint256);
175
+ ) external payable returns (uint256, uint256);
176
176
 
177
177
  /// @notice Executes a sell order
178
178
  /// @param recipient The recipient of the currency
@@ -180,7 +180,13 @@ interface ICoin is IERC165, IERC721Receiver, IERC7572 {
180
180
  /// @param minAmountOut The minimum amount of currency to receive
181
181
  /// @param sqrtPriceLimitX96 The price limit for the swap
182
182
  /// @param tradeReferrer The address of the trade referrer
183
- function sell(address recipient, uint256 orderSize, uint256 minAmountOut, uint160 sqrtPriceLimitX96, address tradeReferrer) external returns (uint256);
183
+ function sell(
184
+ address recipient,
185
+ uint256 orderSize,
186
+ uint256 minAmountOut,
187
+ uint160 sqrtPriceLimitX96,
188
+ address tradeReferrer
189
+ ) external returns (uint256, uint256);
184
190
 
185
191
  /// @notice Enables a user to burn their tokens
186
192
  /// @param amount The amount of tokens to burn
@@ -22,5 +22,11 @@ import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.s
22
22
  OURS TRULY,
23
23
  */
24
24
  contract ZoraFactory is ERC1967Proxy {
25
- constructor(address _logic, bytes memory _data) ERC1967Proxy(_logic, _data) {}
25
+ bytes32 internal immutable name;
26
+
27
+ constructor(address _logic) ERC1967Proxy(_logic, "") {
28
+ // added to create unique bytecode for this contract
29
+ // so that it can be properly verified as its own contract.
30
+ name = keccak256("ZoraFactory");
31
+ }
26
32
  }
@@ -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 "0.4.0";
12
+ return "0.5.0";
13
13
  }
14
14
  }