Skip to content

Commit 116767a

Browse files
committed
feat: treat-list-metadata-as-stringified-json-instead-of-ipfs-uri
1 parent 653df84 commit 116767a

File tree

12 files changed

+278
-273
lines changed

12 files changed

+278
-273
lines changed

contracts/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments
1616

1717
#### Arbitrum Sepolia
1818

19-
- [CurateFactory](https://sepolia.arbiscan.io/address/0xcfd2315053763f6ae964f721e8a6Ea44286a9baF)
20-
- [CurateV2](https://sepolia.arbiscan.io/address/0xd9ea52247FeBd2258823Ff9f4fC49C9cD53fe8de)
21-
- [CurateView](https://sepolia.arbiscan.io/address/0x2532DBf9a2877C1FDd8286f8f9ef51b76184604F)
19+
- [CurateFactory](https://sepolia.arbiscan.io/address/0x3F5768ca9a36d49a8f102E903e44D32a8b84a29F)
20+
- [CurateV2](https://sepolia.arbiscan.io/address/0x7eC8b337bb297c6429794CD888EdcBB3e54A2D20)
21+
- [CurateView](https://sepolia.arbiscan.io/address/0xC153EDAbA561Be9F7E12ACce4079D4a7475d508E)
2222

2323
#### Sepolia
2424

contracts/deploy/00-curate-v2.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,34 @@ const removalTemplate = `{
5454
}
5555
`;
5656

57+
const listMetadata = `{
58+
"title": "Kleros Storytelling - Standard Impact",
59+
"description": "A list of Standard Tier submissions for the Kleros Storytelling Reward Program.",
60+
"columns": [
61+
{
62+
"label": "Title",
63+
"description": "The submission title.",
64+
"type": "text",
65+
"isIdentifier": true
66+
},
67+
{
68+
"label": "Author",
69+
"description": "To easily search submissions by author. This can be a social media handle or a nickname.",
70+
"type": "text",
71+
"isIdentifier": true
72+
},
73+
{
74+
"label": "Link",
75+
"description": "A link to the submission.",
76+
"type": "link"
77+
}
78+
],
79+
"itemName": "story",
80+
"itemNamePlural": "stories",
81+
"logoURI": "/ipfs/QmQN9ZPubns9kpW3jxZefyt8sNbeUzj8KEcsT7i81SiXFf/standard-impact-logo-.png",
82+
"isTCRofTCRs": false
83+
}`;
84+
5785
// General court, 3 jurors
5886
const extraData =
5987
"0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003";
@@ -87,12 +115,11 @@ const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
87115
extraData,
88116
evidenceModule.address,
89117
ethers.ZeroAddress, // _connectedTCR
90-
[registrationTemplate, ""],
91-
[removalTemplate, ""],
92-
disputeTemplateRegistry.address,
118+
[disputeTemplateRegistry.address, [registrationTemplate, ""], [removalTemplate, ""]],
93119
[fee, fee, fee, fee],
94120
timeout,
95-
deployer
121+
deployer,
122+
listMetadata
96123
);
97124

98125
await deploy("CurateFactory", {

contracts/deployments/arbitrumSepoliaDevnet/CurateFactory.json

Lines changed: 25 additions & 32 deletions
Large diffs are not rendered by default.

contracts/deployments/arbitrumSepoliaDevnet/CurateV2.json

Lines changed: 102 additions & 91 deletions
Large diffs are not rendered by default.

contracts/deployments/arbitrumSepoliaDevnet/CurateView.json

Lines changed: 13 additions & 13 deletions
Large diffs are not rendered by default.

contracts/src/CurateFactory.sol

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,16 @@ contract CurateFactory {
1717
// * Events * //
1818
// ************************************* //
1919

20-
/// @dev Emitted when a new Curate contract is deployed using this factory. TODO: change TCR mentions.
20+
/// @dev Emitted when a new Curate contract is deployed using this factory.
2121
/// @param _address The address of the newly deployed Curate contract.
22-
/// @param _listMetadata A link to registry / list metadata (title,description) using its URI
23-
event NewList(CurateV2 indexed _address, string _listMetadata);
22+
event NewList(CurateV2 indexed _address);
2423

2524
// ************************************* //
2625
// * Enums / Structs * //
2726
// ************************************* //
2827

2928
struct TemplateRegistryParams {
30-
address templateRegistry; // The current status of the item.
29+
address templateRegistry; // Template registry address.
3130
string[2] registrationTemplateParameters; // Template and data mappings json for registration requests.
3231
string[2] removalTemplateParameters; // Template and data mappings json for removal requests.
3332
}
@@ -70,7 +69,7 @@ contract CurateFactory {
7069
/// - The base deposit to challenge a removal request.
7170
/// @param _challengePeriodDuration The time in seconds parties have to challenge a request.
7271
/// @param _relayerContract The address of the relay contract to add/remove items directly.
73-
/// @param _listMetadata A link to registry / list metadata (title,description) using its URI
72+
/// @param _listMetadata Stringified JSON object containing list metadata (title, description, isListOfLists, etc.). Example at :- https://cloudflare-ipfs.com/ipfs/QmekLsbXtQfm2jJjdeC5TF1cJcr5qxarZ9bhKmCS9s3ebK/list-metadata.json
7473
function deploy(
7574
address _governor,
7675
IArbitratorV2 _arbitrator,
@@ -90,15 +89,18 @@ contract CurateFactory {
9089
_arbitratorExtraData,
9190
_evidenceModule,
9291
_connectedList,
93-
_templateRegistryParams.registrationTemplateParameters,
94-
_templateRegistryParams.removalTemplateParameters,
95-
_templateRegistryParams.templateRegistry,
92+
CurateV2.TemplateRegistryParams(
93+
_templateRegistryParams.templateRegistry,
94+
_templateRegistryParams.registrationTemplateParameters,
95+
_templateRegistryParams.removalTemplateParameters
96+
),
9697
_baseDeposits,
9798
_challengePeriodDuration,
98-
_relayerContract
99+
_relayerContract,
100+
_listMetadata
99101
);
100102
instances.push(instance);
101-
emit NewList(instance, _listMetadata);
103+
emit NewList(instance);
102104
}
103105

104106
/// @notice Adaptation of https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/Clones.sol.

contracts/src/CurateV2.sol

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ contract CurateV2 is IArbitrableV2 {
7272
EvidenceModule evidenceModule; // The evidence module for the arbitrator.
7373
}
7474

75+
struct TemplateRegistryParams {
76+
address templateRegistry; // Dispute Template registry address
77+
string[2] registrationTemplateParameters; // Template and data mappings json for registration requests.
78+
string[2] removalTemplateParameters; // Template and data mappings json for removal requests.
79+
}
80+
7581
// ************************************* //
7682
// * Storage * //
7783
// ************************************* //
@@ -119,7 +125,7 @@ contract CurateV2 is IArbitrableV2 {
119125

120126
/// @dev Emitted when someone submits an item for the first time.
121127
/// @param _itemID The ID of the new item.
122-
/// @param _data The item data URI.
128+
/// @param _data Stringified JSON Object containing item data. Example at :- https://cloudflare-ipfs.com/ipfs/QmTypFX9416z5V87Fsnf6A89rrskh2X8BSVdaKhwzXNiDb/item.json.
123129
/// @param _addedDirectly Whether the item was added via `addItemDirectly`.
124130
event NewItem(bytes32 indexed _itemID, string _data, bool _addedDirectly);
125131

@@ -146,28 +152,29 @@ contract CurateV2 is IArbitrableV2 {
146152
/// @param _arbitratorExtraData Extra data for the trusted arbitrator contract.
147153
/// @param _evidenceModule The evidence contract for the arbitrator.
148154
/// @param _connectedList The address of the Curate contract that stores related Curate addresses. This parameter can be left empty.
149-
/// @param _registrationTemplateParameters Template and data mappings json for registration requests.
150-
/// @param _removalTemplateParameters Template and data mappings json for removal requests.
151-
/// @param _templateRegistry The dispute template registry.
155+
/// @param _templateRegistryParams The dispute template registry.
156+
/// - templateRegistry : The dispute template registry.
157+
/// - registrationTemplateParameters : Template and data mappings json for registration requests.
158+
/// - removalTemplateParameters : Template and data mappings json for removal requests.
152159
/// @param _baseDeposits The base deposits for requests/challenges as follows:
153160
/// - The base deposit to submit an item.
154161
/// - The base deposit to remove an item.
155162
/// - The base deposit to challenge a submission.
156163
/// - The base deposit to challenge a removal request.
157164
/// @param _challengePeriodDuration The time in seconds parties have to challenge a request.
158165
/// @param _relayerContract The address of the relayer contract to add/remove items directly.
166+
/// @param _listMetadata Stringified JSON object containing list metadata (title, description, isListOfLists, etc.). Example at :- https://cloudflare-ipfs.com/ipfs/QmekLsbXtQfm2jJjdeC5TF1cJcr5qxarZ9bhKmCS9s3ebK/list-metadata.json
159167
function initialize(
160168
address _governor,
161169
IArbitratorV2 _arbitrator,
162170
bytes calldata _arbitratorExtraData,
163171
EvidenceModule _evidenceModule,
164172
address _connectedList,
165-
string[2] calldata _registrationTemplateParameters,
166-
string[2] calldata _removalTemplateParameters,
167-
address _templateRegistry,
173+
TemplateRegistryParams calldata _templateRegistryParams,
168174
uint256[4] calldata _baseDeposits,
169175
uint256 _challengePeriodDuration,
170-
address _relayerContract
176+
address _relayerContract,
177+
string calldata _listMetadata
171178
) external {
172179
require(!initialized, "Already initialized.");
173180
initialized = true;
@@ -180,16 +187,16 @@ contract CurateV2 is IArbitrableV2 {
180187
challengePeriodDuration = _challengePeriodDuration;
181188
relayerContract = _relayerContract;
182189

183-
templateRegistry = IDisputeTemplateRegistry(_templateRegistry);
190+
templateRegistry = IDisputeTemplateRegistry(_templateRegistryParams.templateRegistry);
184191
templateIdRegistration = templateRegistry.setDisputeTemplate(
185192
"Registration",
186-
_registrationTemplateParameters[0],
187-
_registrationTemplateParameters[1]
193+
_templateRegistryParams.registrationTemplateParameters[0],
194+
_templateRegistryParams.registrationTemplateParameters[1]
188195
);
189196
templateIdRemoval = templateRegistry.setDisputeTemplate(
190197
"Removal",
191-
_removalTemplateParameters[0],
192-
_removalTemplateParameters[1]
198+
_templateRegistryParams.removalTemplateParameters[0],
199+
_templateRegistryParams.removalTemplateParameters[1]
193200
);
194201

195202
arbitrationParamsChanges.push(
@@ -203,6 +210,8 @@ contract CurateV2 is IArbitrableV2 {
203210
if (_connectedList != address(0)) {
204211
emit ConnectedListSet(_connectedList);
205212
}
213+
214+
emit ListMetadataSet(_listMetadata);
206215
}
207216

208217
// ************************************* //
@@ -317,7 +326,7 @@ contract CurateV2 is IArbitrableV2 {
317326
// ************************************* //
318327

319328
/// @dev Directly add an item to the list bypassing request-challenge. Can only be used by the relayer contract.
320-
/// @param _item The URI to the item data.
329+
/// @param _item Stringified JSON Object containing Item data
321330
function addItemDirectly(string calldata _item) external onlyRelayer {
322331
bytes32 itemID = keccak256(abi.encodePacked(_item));
323332
Item storage item = items[itemID];
@@ -334,7 +343,7 @@ contract CurateV2 is IArbitrableV2 {
334343
}
335344

336345
/// @dev Directly remove an item from the list bypassing request-challenge. Can only be used by the relayer contract.
337-
/// @param _itemID The ID of the item to remove.
346+
/// @param _itemID The ID of the item to remove. Example at :- https://cloudflare-ipfs.com/ipfs/QmTypFX9416z5V87Fsnf6A89rrskh2X8BSVdaKhwzXNiDb/item.json
338347
function removeItemDirectly(bytes32 _itemID) external onlyRelayer {
339348
Item storage item = items[_itemID];
340349
require(item.status == Status.Registered, "Item must be registered to be removed.");
@@ -345,7 +354,7 @@ contract CurateV2 is IArbitrableV2 {
345354
}
346355

347356
/// @dev Submit a request to register an item. Accepts enough ETH to cover the deposit, reimburses the rest.
348-
/// @param _item The URI to the item data.
357+
/// @param _item Stringified JSON object containing item data. Example at :- https://cloudflare-ipfs.com/ipfs/QmTypFX9416z5V87Fsnf6A89rrskh2X8BSVdaKhwzXNiDb/item.json
349358
function addItem(string calldata _item) external payable {
350359
bytes32 itemID = keccak256(abi.encodePacked(_item));
351360
Item storage item = items[itemID];

subgraph/schema.graphql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ type Registry @entity {
6464
itemName: String
6565
"Plural item name for items in registry."
6666
itemNamePlural: String
67-
"Ipfs uri pointing to file containing the list metadata."
68-
metadataURI: String!
67+
"Stringified JSON data containing registry metadata"
68+
metadata: String
6969
"The parsed data describing the fields in Registry."
7070
fieldProps: [FieldProp!]! @derivedFrom(field: "registry")
7171
}

subgraph/src/Curate.ts

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable prefer-const */
2-
import { log } from "@graphprotocol/graph-ts";
3-
import { Item, Request, Registry } from "../generated/schema";
2+
import { json, log } from "@graphprotocol/graph-ts";
3+
import { Item, Request, Registry, FieldProp } from "../generated/schema";
44

55
import {
66
ItemStatusChange,
@@ -12,11 +12,10 @@ import {
1212
ConnectedListSet,
1313
ListMetadataSet,
1414
} from "../generated/templates/Curate/Curate";
15-
import { ItemStatus, ONE, ZERO, getFinalRuling, getStatus } from "./utils";
15+
import { ItemStatus, JSONValueToBool, JSONValueToMaybeString, ONE, ZERO, getFinalRuling, getStatus } from "./utils";
1616
import { createRequestFromEvent } from "./entities/Request";
1717
import { createItemFromEvent } from "./entities/Item";
1818
import { ensureUser } from "./entities/User";
19-
import { updateRegistryMetadata } from "./CurateFactory";
2019

2120
// Items on a List can be in 1 of 4 states:
2221
// - (0) Absent: The item is not registered on the List and there are no pending requests.
@@ -140,9 +139,61 @@ export function handleListMetadataSet(event: ListMetadataSet): void {
140139
log.error(`Registry {} not found.`, [event.address.toHexString()]);
141140
return;
142141
}
143-
registry.metadataURI = event.params._listMetadata;
144142

145-
updateRegistryMetadata(registry.id, event.params._listMetadata);
143+
registry.metadata = event.params._listMetadata;
144+
145+
let jsonObjValueAndSuccess = json.try_fromString(event.params._listMetadata);
146+
if (!jsonObjValueAndSuccess.isOk) {
147+
log.error(`Error getting json object value for registry metadata {}`, [registry.id]);
148+
registry.save();
149+
return;
150+
}
151+
152+
let jsonObj = jsonObjValueAndSuccess.value.toObject();
153+
if (!jsonObj) {
154+
log.error(`Error converting object for registry metadata {}`, [registry.id]);
155+
registry.save();
156+
return;
157+
}
158+
159+
registry.title = JSONValueToMaybeString(jsonObj.get("title"));
160+
registry.description = JSONValueToMaybeString(jsonObj.get("description"));
161+
registry.logoURI = JSONValueToMaybeString(jsonObj.get("logoURI"));
162+
registry.policyURI = JSONValueToMaybeString(jsonObj.get("policyURI"));
163+
registry.itemName = JSONValueToMaybeString(jsonObj.get("itemName"));
164+
registry.itemNamePlural = JSONValueToMaybeString(jsonObj.get("itemNamePlural"));
165+
registry.isListOfLists = JSONValueToBool(jsonObj.get("isListOfLists"));
166+
167+
let columnsValue = jsonObj.get("columns");
168+
if (!columnsValue) {
169+
log.error(`Error getting column values for registry {}`, [registry.id]);
170+
registry.save();
171+
return;
172+
}
173+
let columns = columnsValue.toArray();
174+
175+
for (let i = 0; i < columns.length; i++) {
176+
let col = columns[i];
177+
let colObj = col.toObject();
178+
179+
let label = colObj.get("label");
180+
181+
let checkedLabel = label ? label.toString() : "missing-label".concat(i.toString());
182+
183+
let description = colObj.get("description");
184+
let _type = colObj.get("type");
185+
let isIdentifier = colObj.get("isIdentifier");
186+
let fieldPropId = registry.id + "@" + checkedLabel;
187+
let fieldProp = new FieldProp(fieldPropId);
188+
189+
fieldProp.type = JSONValueToMaybeString(_type);
190+
fieldProp.label = JSONValueToMaybeString(label);
191+
fieldProp.description = JSONValueToMaybeString(description);
192+
fieldProp.isIdentifier = JSONValueToBool(isIdentifier);
193+
fieldProp.registry = registry.id;
194+
195+
fieldProp.save();
196+
}
146197

147198
registry.save();
148199
}

0 commit comments

Comments
 (0)