@zoralabs/comments-contracts 0.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.
Files changed (140) hide show
  1. package/.env.example +11 -0
  2. package/.turbo/turbo-build.log +60 -0
  3. package/LICENSE +21 -0
  4. package/README.md +70 -0
  5. package/_imagine/Enjoy.sol +41 -0
  6. package/abis/AccessControlUpgradeable.json +250 -0
  7. package/abis/Address.json +29 -0
  8. package/abis/Comments.json +62 -0
  9. package/abis/CommentsDeployerBase.json +15 -0
  10. package/abis/CommentsImpl.json +1750 -0
  11. package/abis/CommentsPermitTest.json +847 -0
  12. package/abis/CommentsTest.json +986 -0
  13. package/abis/CommentsTestBase.json +577 -0
  14. package/abis/Comments_mintAndCommentTest.json +690 -0
  15. package/abis/ContextUpgradeable.json +25 -0
  16. package/abis/ContractVersionBase.json +15 -0
  17. package/abis/Create2.json +28 -0
  18. package/abis/DeployImpl.json +22 -0
  19. package/abis/DeployNonDeterministic.json +22 -0
  20. package/abis/DeployScript.json +22 -0
  21. package/abis/DeterministicDeployerAndCaller.json +315 -0
  22. package/abis/DeterministicUUPSProxyDeployer.json +167 -0
  23. package/abis/ECDSA.json +29 -0
  24. package/abis/EIP712.json +67 -0
  25. package/abis/EIP712UpgradeableWithChainId.json +25 -0
  26. package/abis/ERC1155.json +416 -0
  27. package/abis/ERC1155Holder.json +99 -0
  28. package/abis/ERC165.json +21 -0
  29. package/abis/ERC165Upgradeable.json +44 -0
  30. package/abis/ERC1967Proxy.json +67 -0
  31. package/abis/ERC1967Utils.json +85 -0
  32. package/abis/GenerateDeterministicParams.json +22 -0
  33. package/abis/IAccessControl.json +195 -0
  34. package/abis/IBeacon.json +15 -0
  35. package/abis/IComments.json +654 -0
  36. package/abis/IContractMetadata.json +28 -0
  37. package/abis/IERC1155.json +295 -0
  38. package/abis/IERC1155Errors.json +104 -0
  39. package/abis/IERC1155MetadataURI.json +314 -0
  40. package/abis/IERC1155Receiver.json +99 -0
  41. package/abis/IERC1271.json +26 -0
  42. package/abis/IERC165.json +21 -0
  43. package/abis/IERC1822Proxiable.json +15 -0
  44. package/abis/IERC20.json +224 -0
  45. package/abis/IERC20Errors.json +88 -0
  46. package/abis/IERC5267.json +51 -0
  47. package/abis/IERC721.json +287 -0
  48. package/abis/IERC721Enumerable.json +343 -0
  49. package/abis/IERC721Errors.json +105 -0
  50. package/abis/IERC721Metadata.json +332 -0
  51. package/abis/IERC721TokenReceiver.json +36 -0
  52. package/abis/IHasContractName.json +15 -0
  53. package/abis/IImmutableCreate2Factory.json +93 -0
  54. package/abis/IMulticall3.json +440 -0
  55. package/abis/IProtocolRewards.json +342 -0
  56. package/abis/ISafe.json +15 -0
  57. package/abis/ISymbol.json +15 -0
  58. package/abis/IVersionedContract.json +15 -0
  59. package/abis/IZoraCreator1155.json +343 -0
  60. package/abis/ImmutableCreate2FactoryUtils.json +15 -0
  61. package/abis/Initializable.json +25 -0
  62. package/abis/LibString.json +7 -0
  63. package/abis/Math.json +7 -0
  64. package/abis/Mock1155.json +547 -0
  65. package/abis/MockERC20.json +322 -0
  66. package/abis/MockERC721.json +350 -0
  67. package/abis/MockMinter.json +64 -0
  68. package/abis/OwnableUpgradeable.json +99 -0
  69. package/abis/ProtocolRewards.json +494 -0
  70. package/abis/Proxy.json +6 -0
  71. package/abis/ProxyDeployerScript.json +15 -0
  72. package/abis/ProxyShim.json +112 -0
  73. package/abis/Script.json +15 -0
  74. package/abis/ShortStrings.json +18 -0
  75. package/abis/StdAssertions.json +379 -0
  76. package/abis/StdInvariant.json +180 -0
  77. package/abis/Strings.json +18 -0
  78. package/abis/Test.json +570 -0
  79. package/abis/UUPSUpgradeable.json +130 -0
  80. package/abis/UnorderedNoncesUpgradeable.json +42 -0
  81. package/abis/Vm.json +8627 -0
  82. package/abis/VmSafe.json +7297 -0
  83. package/abis/stdError.json +119 -0
  84. package/abis/stdStorageSafe.json +52 -0
  85. package/addresses/999999999.json +4 -0
  86. package/deterministicConfig/comments.json +8 -0
  87. package/dist/index.cjs +935 -0
  88. package/dist/index.cjs.map +1 -0
  89. package/dist/index.d.ts +2 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +908 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/types.d.ts +4 -0
  94. package/dist/types.d.ts.map +1 -0
  95. package/dist/wagmiGenerated.d.ts +1354 -0
  96. package/dist/wagmiGenerated.d.ts.map +1 -0
  97. package/foundry.toml +24 -0
  98. package/package/index.ts +4 -0
  99. package/package/types.ts +5 -0
  100. package/package/wagmiGenerated.ts +907 -0
  101. package/package.json +62 -0
  102. package/remappings.txt +8 -0
  103. package/script/CommentsDeployerBase.sol +60 -0
  104. package/script/Deploy.s.sol +66 -0
  105. package/script/DeployImpl.s.sol +26 -0
  106. package/script/DeployNonDeterministic.s.sol +43 -0
  107. package/script/GenerateDeterministicParams.s.sol +55 -0
  108. package/script/bundle-abis.ts +109 -0
  109. package/script/storage-check.sh +57 -0
  110. package/script/update-contract-version.ts +63 -0
  111. package/scripts/abis.ts +3 -0
  112. package/scripts/backfillComments.ts +176 -0
  113. package/scripts/generateCommentsTestData.ts +247 -0
  114. package/scripts/getCommentsAddresses.ts +10 -0
  115. package/scripts/queries.ts +73 -0
  116. package/scripts/queryAndSaveComments.ts +48 -0
  117. package/scripts/queryQuantityOfComments.ts +53 -0
  118. package/scripts/signDeployAndCall.ts +51 -0
  119. package/scripts/turnkey.ts +36 -0
  120. package/scripts/utils.ts +127 -0
  121. package/scripts/writeComments.ts +198 -0
  122. package/slither.config.json +7 -0
  123. package/src/CommentsImpl.sol +552 -0
  124. package/src/deployments/CommentsDeployment.sol +14 -0
  125. package/src/interfaces/IComments.sol +156 -0
  126. package/src/interfaces/IZoraCreator1155.sol +12 -0
  127. package/src/proxy/Comments.sol +43 -0
  128. package/src/utils/EIP712UpgradeableWithChainId.sol +36 -0
  129. package/src/version/ContractVersionBase.sol +14 -0
  130. package/test/Comments.t.sol +482 -0
  131. package/test/CommentsTestBase.sol +86 -0
  132. package/test/Comments_mintAndComment.t.sol +101 -0
  133. package/test/Comments_permit.t.sol +397 -0
  134. package/test/mocks/Mock1155.sol +50 -0
  135. package/test/mocks/MockMinter.sol +29 -0
  136. package/test/mocks/ProtocolRewards.sol +1497 -0
  137. package/tsconfig.build.json +10 -0
  138. package/tsconfig.json +9 -0
  139. package/tsup.config.ts +11 -0
  140. package/wagmi.config.ts +14 -0
@@ -0,0 +1,127 @@
1
+ import {
2
+ createPublicClient,
3
+ http,
4
+ Chain,
5
+ createWalletClient,
6
+ PublicClient,
7
+ WalletClient,
8
+ Transport,
9
+ } from "viem";
10
+ import * as chains from "viem/chains";
11
+ import { getChain } from "@zoralabs/chains";
12
+
13
+ export const makeClientsForChain = async (
14
+ chainName: string,
15
+ ): Promise<{
16
+ publicClient: PublicClient;
17
+ walletClient: WalletClient<Transport, Chain>;
18
+ chainId: number;
19
+ }> => {
20
+ const configuredChain = await getChain(chainName);
21
+
22
+ if (configuredChain.id === 9999999) {
23
+ configuredChain.id = chains.zoraSepolia.id;
24
+ }
25
+
26
+ if (!configuredChain) {
27
+ throw new Error(`No chain config found for chain name ${chainName}`);
28
+ }
29
+
30
+ const chainConfig = Object.values(chains).find(
31
+ (x) => x.id === configuredChain.id,
32
+ );
33
+
34
+ if (!chainConfig) {
35
+ throw new Error(`No chain config found for chain id ${configuredChain.id}`);
36
+ }
37
+
38
+ const rpcUrl = configuredChain.rpcUrl;
39
+
40
+ if (!rpcUrl) {
41
+ throw new Error(`No RPC found for chain id ${configuredChain.id}`);
42
+ }
43
+
44
+ return {
45
+ publicClient: createPublicClient({
46
+ transport: http(),
47
+ chain: {
48
+ ...chainConfig,
49
+ rpcUrls: {
50
+ default: {
51
+ http: [rpcUrl],
52
+ },
53
+ public: {
54
+ http: [rpcUrl],
55
+ },
56
+ },
57
+ },
58
+ }) as PublicClient,
59
+ walletClient: createWalletClient({
60
+ transport: http(),
61
+ chain: {
62
+ ...chainConfig,
63
+ rpcUrls: {
64
+ default: {
65
+ http: [rpcUrl],
66
+ },
67
+ public: {
68
+ http: [rpcUrl],
69
+ },
70
+ },
71
+ },
72
+ }),
73
+ chainId: configuredChain.id as number,
74
+ };
75
+ };
76
+
77
+ export const makeWalletClientForChain = async (chainName: string) => {
78
+ const configuredChain = await getChain(chainName);
79
+
80
+ if (configuredChain.id === 9999999) {
81
+ configuredChain.id = chains.zoraSepolia.id;
82
+ }
83
+ };
84
+ export function getChainNamePositionalArg() {
85
+ // parse chain id as first argument:
86
+ const chainName = process.argv[2];
87
+
88
+ if (!chainName) {
89
+ throw new Error("Must provide chain name as first argument");
90
+ }
91
+
92
+ return chainName;
93
+ }
94
+
95
+ const CONFIG_BASE =
96
+ "https://api.goldsky.com/api/public/project_clhk16b61ay9t49vm6ntn4mkz/subgraphs";
97
+
98
+ export function getSubgraph(name: string, version: string = "stable"): string {
99
+ return `${CONFIG_BASE}/${name}/${version}/gn`;
100
+ }
101
+
102
+ const subgraphChainName = (chainName: string) => {
103
+ if (chainName === "zora") {
104
+ return "zora-mainnet";
105
+ }
106
+ if (chainName === "base") {
107
+ return "base-mainnet";
108
+ }
109
+
110
+ return chainName;
111
+ };
112
+
113
+ export async function getChainConfig(chainName: string) {
114
+ const subgraph = getSubgraph(
115
+ `zora-create-${subgraphChainName(chainName)}`,
116
+ "stable",
117
+ );
118
+ const { publicClient, walletClient, chainId } =
119
+ await makeClientsForChain(chainName);
120
+
121
+ return {
122
+ publicClient: publicClient as PublicClient<Transport, Chain>,
123
+ walletClient: walletClient as WalletClient<Transport, Chain>,
124
+ chainId,
125
+ subgraph,
126
+ };
127
+ }
@@ -0,0 +1,198 @@
1
+ import {
2
+ Address,
3
+ WalletClient,
4
+ PublicClient,
5
+ toHex,
6
+ BaseError,
7
+ ContractFunctionRevertedError,
8
+ ExecutionRevertedError,
9
+ TransactionExecutionError,
10
+ ContractFunctionExecutionError,
11
+ Account,
12
+ Hex,
13
+ Chain,
14
+ Transport,
15
+ } from "viem";
16
+ import { privateKeyToAccount } from "viem/accounts";
17
+ import { getCommentsAddress } from "./getCommentsAddresses";
18
+ import { commentsImplABI } from "../package/wagmiGenerated";
19
+ import { CommentIdentifier } from "../package/types";
20
+ import { MintComment } from "./queries";
21
+
22
+ const blockAndLogIndexToId = (
23
+ blockString: string,
24
+ logIndexString: string,
25
+ ): Hex => {
26
+ const blockNumber = BigInt(blockString);
27
+ const logIndex = BigInt(logIndexString);
28
+
29
+ // Use a larger shift (192 bits instead of 128)
30
+ const blockAndLogIndex = (blockNumber << 200n) | logIndex;
31
+
32
+ return toHex(blockAndLogIndex, { size: 32 });
33
+ };
34
+
35
+ export const getBackfillerAccount = () => {
36
+ const privateKey = process.env.PRIVATE_KEY as Address;
37
+ return privateKeyToAccount(privateKey);
38
+ };
39
+
40
+ const parseError = (err: Error) => {
41
+ if (err instanceof BaseError) {
42
+ const revertError = err.walk(
43
+ (_err) =>
44
+ _err instanceof ContractFunctionRevertedError ||
45
+ _err instanceof ExecutionRevertedError ||
46
+ _err instanceof TransactionExecutionError ||
47
+ _err instanceof ContractFunctionExecutionError,
48
+ );
49
+ if (
50
+ revertError instanceof ContractFunctionRevertedError ||
51
+ revertError instanceof ExecutionRevertedError ||
52
+ revertError instanceof TransactionExecutionError ||
53
+ revertError instanceof ContractFunctionExecutionError
54
+ ) {
55
+ // @ts-ignore
56
+ const errorName = revertError.data?.errorName ?? "";
57
+ console.error("reverted", {
58
+ errorName,
59
+ // details: revertError.details,
60
+ message: revertError.message,
61
+ shortMessage: revertError.shortMessage,
62
+ });
63
+
64
+ throw err;
65
+ }
66
+ }
67
+
68
+ console.error("Unknown error", err.name);
69
+ };
70
+
71
+ function toCommentIdentifier(comment: MintComment): CommentIdentifier {
72
+ return {
73
+ commenter: comment.sender,
74
+ contractAddress: comment.tokenAndContract.address,
75
+ tokenId: BigInt(comment.tokenAndContract.tokenId),
76
+ nonce: blockAndLogIndexToId(comment.txn.block, comment.txn.logIndex),
77
+ };
78
+ }
79
+
80
+ export const writeCommentsToContract = async ({
81
+ comments,
82
+ walletClient,
83
+ publicClient,
84
+ chainId,
85
+ account,
86
+ write = true,
87
+ }: {
88
+ comments: MintComment[];
89
+ walletClient: WalletClient<Transport, Chain>;
90
+ publicClient: PublicClient;
91
+ chainId: number;
92
+ account: Account;
93
+ // if the transaction should be written to the chain
94
+ write?: boolean;
95
+ }) => {
96
+ const commentsAddress = (await getCommentsAddress(chainId)).COMMENTS;
97
+
98
+ const commentIdentifiers = comments.map((comment): CommentIdentifier => {
99
+ try {
100
+ return {
101
+ commenter: comment.sender,
102
+ contractAddress: comment.tokenAndContract.address,
103
+ tokenId: BigInt(comment.tokenAndContract.tokenId),
104
+ nonce: blockAndLogIndexToId(comment.txn.block, comment.txn.logIndex),
105
+ };
106
+ } catch (err) {
107
+ console.error("Failed to parse comment", comment);
108
+ throw err;
109
+ }
110
+ });
111
+
112
+ const texts = comments.map((comment) => comment.comment);
113
+
114
+ const timestamps = comments.map((comment) => BigInt(comment.timestamp));
115
+
116
+ const originalTransactionHashes = comments.map((comment) => comment.txn.id);
117
+
118
+ if (!write) {
119
+ console.log("simulating");
120
+
121
+ try {
122
+ const simulated = await publicClient.simulateContract({
123
+ abi: commentsImplABI,
124
+ address: commentsAddress,
125
+ functionName: "backfillBatchAddComment",
126
+ args: [
127
+ commentIdentifiers,
128
+ texts,
129
+ timestamps,
130
+ originalTransactionHashes,
131
+ ],
132
+ account,
133
+ });
134
+
135
+ console.log("simulated:", {
136
+ gas: simulated.request.gas,
137
+ gasPrice: simulated.request.gasPrice,
138
+ });
139
+ } catch (err) {
140
+ parseError(err);
141
+ }
142
+ return;
143
+ }
144
+
145
+ console.log("writing comments");
146
+
147
+ let hash;
148
+
149
+ try {
150
+ hash = await walletClient.writeContract({
151
+ abi: commentsImplABI,
152
+ address: commentsAddress,
153
+ functionName: "backfillBatchAddComment",
154
+ args: [commentIdentifiers, texts, timestamps, originalTransactionHashes],
155
+ account,
156
+ });
157
+ } catch (err) {
158
+ parseError(err);
159
+ return;
160
+ }
161
+
162
+ const receipt = await publicClient.waitForTransactionReceipt({
163
+ hash,
164
+ });
165
+
166
+ if (receipt.status !== "success") {
167
+ throw new Error("Transaction failed");
168
+ }
169
+
170
+ console.log("wrote comments", {
171
+ status: receipt.status,
172
+ gasUsed: receipt.gasUsed,
173
+ });
174
+ };
175
+
176
+ export const filterCommentsThatAreAlreadyOnChain = async ({
177
+ comments,
178
+ chainId,
179
+ publicClient,
180
+ }: {
181
+ comments: MintComment[];
182
+ chainId: number;
183
+ publicClient: PublicClient;
184
+ }) => {
185
+ const commentsAddress = (await getCommentsAddress(chainId)).COMMENTS;
186
+
187
+ const result = await publicClient.multicall({
188
+ allowFailure: false,
189
+ contracts: comments.map((comment) => ({
190
+ abi: commentsImplABI,
191
+ address: commentsAddress,
192
+ functionName: "hashAndCheckCommentExists",
193
+ args: [toCommentIdentifier(comment)],
194
+ })),
195
+ });
196
+
197
+ return comments.filter((_, index) => !result[index][1]);
198
+ };
@@ -0,0 +1,7 @@
1
+ {
2
+ "filter_paths": "(node_modules/,test/)",
3
+ "solc_remaps": [
4
+ "@zoralabs/=node_modules/@zoralabs/",
5
+ "@openzeppelin/=node_modules/@openzeppelin/"
6
+ ]
7
+ }