@latticexyz/world-modules 2.0.12-type-resolutions-effc7ab1 → 2.0.12-type-resolutions-ad8cc987
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/cache/solidity-files-cache.json +1 -1
- package/package.json +9 -8
- package/src/index.sol +25 -0
- package/src/interfaces/IBaseWorld.sol +16 -0
- package/src/interfaces/IERC20System.sol +33 -0
- package/src/interfaces/IERC721System.sol +43 -0
- package/src/interfaces/IPuppetFactorySystem.sol +15 -0
- package/src/interfaces/IUniqueEntitySystem.sol +13 -0
- package/src/interfaces/IUnstable_CallWithSignatureSystem.sol +20 -0
- package/src/modules/callwithsignature/ECDSA.sol +174 -0
- package/src/modules/callwithsignature/IERC1271.sol +17 -0
- package/src/modules/callwithsignature/IUnstable_CallWithSignatureErrors.sol +9 -0
- package/src/modules/callwithsignature/SignatureChecker.sol +50 -0
- package/src/modules/callwithsignature/Unstable_CallWithSignatureModule.sol +48 -0
- package/src/modules/callwithsignature/Unstable_CallWithSignatureSystem.sol +36 -0
- package/src/modules/callwithsignature/constants.sol +10 -0
- package/src/modules/callwithsignature/getSignedMessageHash.sol +54 -0
- package/src/modules/callwithsignature/tables/CallWithSignatureNonces.sol +199 -0
- package/src/modules/callwithsignature/validateCallWithSignature.sol +31 -0
- package/src/modules/erc20-puppet/ERC20Module.sol +88 -0
- package/src/modules/erc20-puppet/ERC20System.sol +286 -0
- package/src/modules/erc20-puppet/IERC20.sol +94 -0
- package/src/modules/erc20-puppet/IERC20Errors.sol +49 -0
- package/src/modules/erc20-puppet/IERC20Events.sol +18 -0
- package/src/modules/erc20-puppet/IERC20Mintable.sol +25 -0
- package/src/modules/erc20-puppet/constants.sol +20 -0
- package/src/modules/erc20-puppet/registerERC20.sol +35 -0
- package/src/modules/erc20-puppet/tables/Allowances.sol +208 -0
- package/src/modules/erc20-puppet/tables/ERC20Metadata.sol +604 -0
- package/src/modules/erc20-puppet/tables/ERC20Registry.sol +199 -0
- package/src/modules/erc20-puppet/tables/TotalSupply.sol +184 -0
- package/src/modules/erc20-puppet/utils.sol +30 -0
- package/src/modules/erc721-puppet/ERC721Module.sol +95 -0
- package/src/modules/erc721-puppet/ERC721System.sol +531 -0
- package/src/modules/erc721-puppet/IERC721.sol +120 -0
- package/src/modules/erc721-puppet/IERC721Errors.sol +61 -0
- package/src/modules/erc721-puppet/IERC721Events.sol +23 -0
- package/src/modules/erc721-puppet/IERC721Metadata.sol +27 -0
- package/src/modules/erc721-puppet/IERC721Mintable.sol +53 -0
- package/src/modules/erc721-puppet/IERC721Receiver.sol +28 -0
- package/src/modules/erc721-puppet/constants.sol +23 -0
- package/src/modules/erc721-puppet/libraries/LibString.sol +77 -0
- package/src/modules/erc721-puppet/registerERC721.sol +37 -0
- package/src/modules/erc721-puppet/tables/ERC721Metadata.sol +703 -0
- package/src/modules/erc721-puppet/tables/ERC721Registry.sol +199 -0
- package/src/modules/erc721-puppet/tables/OperatorApproval.sol +220 -0
- package/src/modules/erc721-puppet/tables/Owners.sol +196 -0
- package/src/modules/erc721-puppet/tables/TokenApproval.sol +196 -0
- package/src/modules/erc721-puppet/tables/TokenURI.sol +450 -0
- package/src/modules/erc721-puppet/utils.sol +38 -0
- package/src/modules/keysintable/KeysInTableHook.sol +141 -0
- package/src/modules/keysintable/KeysInTableModule.sol +110 -0
- package/src/modules/keysintable/constants.sol +7 -0
- package/src/modules/keysintable/getKeysInTable.sol +81 -0
- package/src/modules/keysintable/hasKey.sol +28 -0
- package/src/modules/keysintable/query.sol +200 -0
- package/src/modules/keysintable/tables/KeysInTable.sol +1638 -0
- package/src/modules/keysintable/tables/UsedKeysIndex.sol +414 -0
- package/src/modules/keyswithvalue/KeysWithValueHook.sol +158 -0
- package/src/modules/keyswithvalue/KeysWithValueModule.sol +103 -0
- package/src/modules/keyswithvalue/constants.sol +7 -0
- package/src/modules/keyswithvalue/getKeysWithValue.sol +58 -0
- package/src/modules/keyswithvalue/getTargetTableId.sol +32 -0
- package/src/modules/keyswithvalue/tables/KeysWithValue.sol +668 -0
- package/src/modules/puppet/Puppet.sol +80 -0
- package/src/modules/puppet/PuppetDelegationControl.sol +17 -0
- package/src/modules/puppet/PuppetFactorySystem.sol +25 -0
- package/src/modules/puppet/PuppetMaster.sol +19 -0
- package/src/modules/puppet/PuppetModule.sol +64 -0
- package/src/modules/puppet/constants.sol +23 -0
- package/src/modules/puppet/createPuppet.sol +24 -0
- package/src/modules/puppet/tables/PuppetRegistry.sol +199 -0
- package/src/modules/puppet/utils.sol +10 -0
- package/src/modules/std-delegations/CallboundDelegationControl.sol +64 -0
- package/src/modules/std-delegations/StandardDelegationsModule.sol +55 -0
- package/src/modules/std-delegations/SystemboundDelegationControl.sol +54 -0
- package/src/modules/std-delegations/TimeboundDelegationControl.sol +27 -0
- package/src/modules/std-delegations/constants.sol +21 -0
- package/src/modules/std-delegations/tables/CallboundDelegations.sol +287 -0
- package/src/modules/std-delegations/tables/SystemboundDelegations.sol +256 -0
- package/src/modules/std-delegations/tables/TimeboundDelegations.sol +211 -0
- package/src/modules/tokens/tables/Balances.sol +196 -0
- package/src/modules/uniqueentity/UniqueEntityModule.sol +73 -0
- package/src/modules/uniqueentity/UniqueEntitySystem.sol +18 -0
- package/src/modules/uniqueentity/constants.sol +13 -0
- package/src/modules/uniqueentity/getUniqueEntity.sol +26 -0
- package/src/modules/uniqueentity/tables/UniqueEntity.sol +238 -0
- package/src/modules/utils/ArrayLib.sol +55 -0
- package/src/utils/AccessControlLib.sol +55 -0
- package/src/utils/SystemSwitch.sol +80 -0
@@ -0,0 +1,414 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
/* Autogenerated file. Do not edit manually. */
|
5
|
+
|
6
|
+
// Import store internals
|
7
|
+
import { IStore } from "@latticexyz/store/src/IStore.sol";
|
8
|
+
import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol";
|
9
|
+
import { StoreCore } from "@latticexyz/store/src/StoreCore.sol";
|
10
|
+
import { Bytes } from "@latticexyz/store/src/Bytes.sol";
|
11
|
+
import { Memory } from "@latticexyz/store/src/Memory.sol";
|
12
|
+
import { SliceLib } from "@latticexyz/store/src/Slice.sol";
|
13
|
+
import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol";
|
14
|
+
import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol";
|
15
|
+
import { Schema } from "@latticexyz/store/src/Schema.sol";
|
16
|
+
import { EncodedLengths, EncodedLengthsLib } from "@latticexyz/store/src/EncodedLengths.sol";
|
17
|
+
import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
|
18
|
+
|
19
|
+
// Import user types
|
20
|
+
import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
|
21
|
+
|
22
|
+
library UsedKeysIndex {
|
23
|
+
// Hex below is the result of `WorldResourceIdLib.encode({ namespace: "", name: "UsedKeysIndex", typeId: RESOURCE_TABLE });`
|
24
|
+
ResourceId constant _tableId = ResourceId.wrap(0x74620000000000000000000000000000557365644b657973496e646578000000);
|
25
|
+
|
26
|
+
FieldLayout constant _fieldLayout =
|
27
|
+
FieldLayout.wrap(0x0006020001050000000000000000000000000000000000000000000000000000);
|
28
|
+
|
29
|
+
// Hex-encoded key schema of (bytes32, bytes32)
|
30
|
+
Schema constant _keySchema = Schema.wrap(0x004002005f5f0000000000000000000000000000000000000000000000000000);
|
31
|
+
// Hex-encoded value schema of (bool, uint40)
|
32
|
+
Schema constant _valueSchema = Schema.wrap(0x0006020060040000000000000000000000000000000000000000000000000000);
|
33
|
+
|
34
|
+
/**
|
35
|
+
* @notice Get the table's key field names.
|
36
|
+
* @return keyNames An array of strings with the names of key fields.
|
37
|
+
*/
|
38
|
+
function getKeyNames() internal pure returns (string[] memory keyNames) {
|
39
|
+
keyNames = new string[](2);
|
40
|
+
keyNames[0] = "sourceTableId";
|
41
|
+
keyNames[1] = "keysHash";
|
42
|
+
}
|
43
|
+
|
44
|
+
/**
|
45
|
+
* @notice Get the table's value field names.
|
46
|
+
* @return fieldNames An array of strings with the names of value fields.
|
47
|
+
*/
|
48
|
+
function getFieldNames() internal pure returns (string[] memory fieldNames) {
|
49
|
+
fieldNames = new string[](2);
|
50
|
+
fieldNames[0] = "has";
|
51
|
+
fieldNames[1] = "index";
|
52
|
+
}
|
53
|
+
|
54
|
+
/**
|
55
|
+
* @notice Register the table with its config.
|
56
|
+
*/
|
57
|
+
function register() internal {
|
58
|
+
StoreSwitch.registerTable(_tableId, _fieldLayout, _keySchema, _valueSchema, getKeyNames(), getFieldNames());
|
59
|
+
}
|
60
|
+
|
61
|
+
/**
|
62
|
+
* @notice Register the table with its config.
|
63
|
+
*/
|
64
|
+
function _register() internal {
|
65
|
+
StoreCore.registerTable(_tableId, _fieldLayout, _keySchema, _valueSchema, getKeyNames(), getFieldNames());
|
66
|
+
}
|
67
|
+
|
68
|
+
/**
|
69
|
+
* @notice Register the table with its config (using the specified store).
|
70
|
+
*/
|
71
|
+
function register(IStore _store) internal {
|
72
|
+
_store.registerTable(_tableId, _fieldLayout, _keySchema, _valueSchema, getKeyNames(), getFieldNames());
|
73
|
+
}
|
74
|
+
|
75
|
+
/**
|
76
|
+
* @notice Get has.
|
77
|
+
*/
|
78
|
+
function getHas(ResourceId sourceTableId, bytes32 keysHash) internal view returns (bool has) {
|
79
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
80
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
81
|
+
_keyTuple[1] = keysHash;
|
82
|
+
|
83
|
+
bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout);
|
84
|
+
return (_toBool(uint8(bytes1(_blob))));
|
85
|
+
}
|
86
|
+
|
87
|
+
/**
|
88
|
+
* @notice Get has.
|
89
|
+
*/
|
90
|
+
function _getHas(ResourceId sourceTableId, bytes32 keysHash) internal view returns (bool has) {
|
91
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
92
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
93
|
+
_keyTuple[1] = keysHash;
|
94
|
+
|
95
|
+
bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout);
|
96
|
+
return (_toBool(uint8(bytes1(_blob))));
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* @notice Get has (using the specified store).
|
101
|
+
*/
|
102
|
+
function getHas(IStore _store, ResourceId sourceTableId, bytes32 keysHash) internal view returns (bool has) {
|
103
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
104
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
105
|
+
_keyTuple[1] = keysHash;
|
106
|
+
|
107
|
+
bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout);
|
108
|
+
return (_toBool(uint8(bytes1(_blob))));
|
109
|
+
}
|
110
|
+
|
111
|
+
/**
|
112
|
+
* @notice Set has.
|
113
|
+
*/
|
114
|
+
function setHas(ResourceId sourceTableId, bytes32 keysHash, bool has) internal {
|
115
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
116
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
117
|
+
_keyTuple[1] = keysHash;
|
118
|
+
|
119
|
+
StoreSwitch.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((has)), _fieldLayout);
|
120
|
+
}
|
121
|
+
|
122
|
+
/**
|
123
|
+
* @notice Set has.
|
124
|
+
*/
|
125
|
+
function _setHas(ResourceId sourceTableId, bytes32 keysHash, bool has) internal {
|
126
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
127
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
128
|
+
_keyTuple[1] = keysHash;
|
129
|
+
|
130
|
+
StoreCore.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((has)), _fieldLayout);
|
131
|
+
}
|
132
|
+
|
133
|
+
/**
|
134
|
+
* @notice Set has (using the specified store).
|
135
|
+
*/
|
136
|
+
function setHas(IStore _store, ResourceId sourceTableId, bytes32 keysHash, bool has) internal {
|
137
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
138
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
139
|
+
_keyTuple[1] = keysHash;
|
140
|
+
|
141
|
+
_store.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((has)), _fieldLayout);
|
142
|
+
}
|
143
|
+
|
144
|
+
/**
|
145
|
+
* @notice Get index.
|
146
|
+
*/
|
147
|
+
function getIndex(ResourceId sourceTableId, bytes32 keysHash) internal view returns (uint40 index) {
|
148
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
149
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
150
|
+
_keyTuple[1] = keysHash;
|
151
|
+
|
152
|
+
bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout);
|
153
|
+
return (uint40(bytes5(_blob)));
|
154
|
+
}
|
155
|
+
|
156
|
+
/**
|
157
|
+
* @notice Get index.
|
158
|
+
*/
|
159
|
+
function _getIndex(ResourceId sourceTableId, bytes32 keysHash) internal view returns (uint40 index) {
|
160
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
161
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
162
|
+
_keyTuple[1] = keysHash;
|
163
|
+
|
164
|
+
bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout);
|
165
|
+
return (uint40(bytes5(_blob)));
|
166
|
+
}
|
167
|
+
|
168
|
+
/**
|
169
|
+
* @notice Get index (using the specified store).
|
170
|
+
*/
|
171
|
+
function getIndex(IStore _store, ResourceId sourceTableId, bytes32 keysHash) internal view returns (uint40 index) {
|
172
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
173
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
174
|
+
_keyTuple[1] = keysHash;
|
175
|
+
|
176
|
+
bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 1, _fieldLayout);
|
177
|
+
return (uint40(bytes5(_blob)));
|
178
|
+
}
|
179
|
+
|
180
|
+
/**
|
181
|
+
* @notice Set index.
|
182
|
+
*/
|
183
|
+
function setIndex(ResourceId sourceTableId, bytes32 keysHash, uint40 index) internal {
|
184
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
185
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
186
|
+
_keyTuple[1] = keysHash;
|
187
|
+
|
188
|
+
StoreSwitch.setStaticField(_tableId, _keyTuple, 1, abi.encodePacked((index)), _fieldLayout);
|
189
|
+
}
|
190
|
+
|
191
|
+
/**
|
192
|
+
* @notice Set index.
|
193
|
+
*/
|
194
|
+
function _setIndex(ResourceId sourceTableId, bytes32 keysHash, uint40 index) internal {
|
195
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
196
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
197
|
+
_keyTuple[1] = keysHash;
|
198
|
+
|
199
|
+
StoreCore.setStaticField(_tableId, _keyTuple, 1, abi.encodePacked((index)), _fieldLayout);
|
200
|
+
}
|
201
|
+
|
202
|
+
/**
|
203
|
+
* @notice Set index (using the specified store).
|
204
|
+
*/
|
205
|
+
function setIndex(IStore _store, ResourceId sourceTableId, bytes32 keysHash, uint40 index) internal {
|
206
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
207
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
208
|
+
_keyTuple[1] = keysHash;
|
209
|
+
|
210
|
+
_store.setStaticField(_tableId, _keyTuple, 1, abi.encodePacked((index)), _fieldLayout);
|
211
|
+
}
|
212
|
+
|
213
|
+
/**
|
214
|
+
* @notice Get the full data.
|
215
|
+
*/
|
216
|
+
function get(ResourceId sourceTableId, bytes32 keysHash) internal view returns (bool has, uint40 index) {
|
217
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
218
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
219
|
+
_keyTuple[1] = keysHash;
|
220
|
+
|
221
|
+
(bytes memory _staticData, EncodedLengths _encodedLengths, bytes memory _dynamicData) = StoreSwitch.getRecord(
|
222
|
+
_tableId,
|
223
|
+
_keyTuple,
|
224
|
+
_fieldLayout
|
225
|
+
);
|
226
|
+
return decode(_staticData, _encodedLengths, _dynamicData);
|
227
|
+
}
|
228
|
+
|
229
|
+
/**
|
230
|
+
* @notice Get the full data.
|
231
|
+
*/
|
232
|
+
function _get(ResourceId sourceTableId, bytes32 keysHash) internal view returns (bool has, uint40 index) {
|
233
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
234
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
235
|
+
_keyTuple[1] = keysHash;
|
236
|
+
|
237
|
+
(bytes memory _staticData, EncodedLengths _encodedLengths, bytes memory _dynamicData) = StoreCore.getRecord(
|
238
|
+
_tableId,
|
239
|
+
_keyTuple,
|
240
|
+
_fieldLayout
|
241
|
+
);
|
242
|
+
return decode(_staticData, _encodedLengths, _dynamicData);
|
243
|
+
}
|
244
|
+
|
245
|
+
/**
|
246
|
+
* @notice Get the full data (using the specified store).
|
247
|
+
*/
|
248
|
+
function get(
|
249
|
+
IStore _store,
|
250
|
+
ResourceId sourceTableId,
|
251
|
+
bytes32 keysHash
|
252
|
+
) internal view returns (bool has, uint40 index) {
|
253
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
254
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
255
|
+
_keyTuple[1] = keysHash;
|
256
|
+
|
257
|
+
(bytes memory _staticData, EncodedLengths _encodedLengths, bytes memory _dynamicData) = _store.getRecord(
|
258
|
+
_tableId,
|
259
|
+
_keyTuple,
|
260
|
+
_fieldLayout
|
261
|
+
);
|
262
|
+
return decode(_staticData, _encodedLengths, _dynamicData);
|
263
|
+
}
|
264
|
+
|
265
|
+
/**
|
266
|
+
* @notice Set the full data using individual values.
|
267
|
+
*/
|
268
|
+
function set(ResourceId sourceTableId, bytes32 keysHash, bool has, uint40 index) internal {
|
269
|
+
bytes memory _staticData = encodeStatic(has, index);
|
270
|
+
|
271
|
+
EncodedLengths _encodedLengths;
|
272
|
+
bytes memory _dynamicData;
|
273
|
+
|
274
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
275
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
276
|
+
_keyTuple[1] = keysHash;
|
277
|
+
|
278
|
+
StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData);
|
279
|
+
}
|
280
|
+
|
281
|
+
/**
|
282
|
+
* @notice Set the full data using individual values.
|
283
|
+
*/
|
284
|
+
function _set(ResourceId sourceTableId, bytes32 keysHash, bool has, uint40 index) internal {
|
285
|
+
bytes memory _staticData = encodeStatic(has, index);
|
286
|
+
|
287
|
+
EncodedLengths _encodedLengths;
|
288
|
+
bytes memory _dynamicData;
|
289
|
+
|
290
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
291
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
292
|
+
_keyTuple[1] = keysHash;
|
293
|
+
|
294
|
+
StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout);
|
295
|
+
}
|
296
|
+
|
297
|
+
/**
|
298
|
+
* @notice Set the full data using individual values (using the specified store).
|
299
|
+
*/
|
300
|
+
function set(IStore _store, ResourceId sourceTableId, bytes32 keysHash, bool has, uint40 index) internal {
|
301
|
+
bytes memory _staticData = encodeStatic(has, index);
|
302
|
+
|
303
|
+
EncodedLengths _encodedLengths;
|
304
|
+
bytes memory _dynamicData;
|
305
|
+
|
306
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
307
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
308
|
+
_keyTuple[1] = keysHash;
|
309
|
+
|
310
|
+
_store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData);
|
311
|
+
}
|
312
|
+
|
313
|
+
/**
|
314
|
+
* @notice Decode the tightly packed blob of static data using this table's field layout.
|
315
|
+
*/
|
316
|
+
function decodeStatic(bytes memory _blob) internal pure returns (bool has, uint40 index) {
|
317
|
+
has = (_toBool(uint8(Bytes.getBytes1(_blob, 0))));
|
318
|
+
|
319
|
+
index = (uint40(Bytes.getBytes5(_blob, 1)));
|
320
|
+
}
|
321
|
+
|
322
|
+
/**
|
323
|
+
* @notice Decode the tightly packed blobs using this table's field layout.
|
324
|
+
* @param _staticData Tightly packed static fields.
|
325
|
+
*
|
326
|
+
*
|
327
|
+
*/
|
328
|
+
function decode(
|
329
|
+
bytes memory _staticData,
|
330
|
+
EncodedLengths,
|
331
|
+
bytes memory
|
332
|
+
) internal pure returns (bool has, uint40 index) {
|
333
|
+
(has, index) = decodeStatic(_staticData);
|
334
|
+
}
|
335
|
+
|
336
|
+
/**
|
337
|
+
* @notice Delete all data for given keys.
|
338
|
+
*/
|
339
|
+
function deleteRecord(ResourceId sourceTableId, bytes32 keysHash) internal {
|
340
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
341
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
342
|
+
_keyTuple[1] = keysHash;
|
343
|
+
|
344
|
+
StoreSwitch.deleteRecord(_tableId, _keyTuple);
|
345
|
+
}
|
346
|
+
|
347
|
+
/**
|
348
|
+
* @notice Delete all data for given keys.
|
349
|
+
*/
|
350
|
+
function _deleteRecord(ResourceId sourceTableId, bytes32 keysHash) internal {
|
351
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
352
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
353
|
+
_keyTuple[1] = keysHash;
|
354
|
+
|
355
|
+
StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout);
|
356
|
+
}
|
357
|
+
|
358
|
+
/**
|
359
|
+
* @notice Delete all data for given keys (using the specified store).
|
360
|
+
*/
|
361
|
+
function deleteRecord(IStore _store, ResourceId sourceTableId, bytes32 keysHash) internal {
|
362
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
363
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
364
|
+
_keyTuple[1] = keysHash;
|
365
|
+
|
366
|
+
_store.deleteRecord(_tableId, _keyTuple);
|
367
|
+
}
|
368
|
+
|
369
|
+
/**
|
370
|
+
* @notice Tightly pack static (fixed length) data using this table's schema.
|
371
|
+
* @return The static data, encoded into a sequence of bytes.
|
372
|
+
*/
|
373
|
+
function encodeStatic(bool has, uint40 index) internal pure returns (bytes memory) {
|
374
|
+
return abi.encodePacked(has, index);
|
375
|
+
}
|
376
|
+
|
377
|
+
/**
|
378
|
+
* @notice Encode all of a record's fields.
|
379
|
+
* @return The static (fixed length) data, encoded into a sequence of bytes.
|
380
|
+
* @return The lengths of the dynamic fields (packed into a single bytes32 value).
|
381
|
+
* @return The dynamic (variable length) data, encoded into a sequence of bytes.
|
382
|
+
*/
|
383
|
+
function encode(bool has, uint40 index) internal pure returns (bytes memory, EncodedLengths, bytes memory) {
|
384
|
+
bytes memory _staticData = encodeStatic(has, index);
|
385
|
+
|
386
|
+
EncodedLengths _encodedLengths;
|
387
|
+
bytes memory _dynamicData;
|
388
|
+
|
389
|
+
return (_staticData, _encodedLengths, _dynamicData);
|
390
|
+
}
|
391
|
+
|
392
|
+
/**
|
393
|
+
* @notice Encode keys as a bytes32 array using this table's field layout.
|
394
|
+
*/
|
395
|
+
function encodeKeyTuple(ResourceId sourceTableId, bytes32 keysHash) internal pure returns (bytes32[] memory) {
|
396
|
+
bytes32[] memory _keyTuple = new bytes32[](2);
|
397
|
+
_keyTuple[0] = ResourceId.unwrap(sourceTableId);
|
398
|
+
_keyTuple[1] = keysHash;
|
399
|
+
|
400
|
+
return _keyTuple;
|
401
|
+
}
|
402
|
+
}
|
403
|
+
|
404
|
+
/**
|
405
|
+
* @notice Cast a value to a bool.
|
406
|
+
* @dev Boolean values are encoded as uint8 (1 = true, 0 = false), but Solidity doesn't allow casting between uint8 and bool.
|
407
|
+
* @param value The uint8 value to convert.
|
408
|
+
* @return result The boolean value.
|
409
|
+
*/
|
410
|
+
function _toBool(uint8 value) pure returns (bool result) {
|
411
|
+
assembly {
|
412
|
+
result := value
|
413
|
+
}
|
414
|
+
}
|
@@ -0,0 +1,158 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
import { StoreHook } from "@latticexyz/store/src/StoreHook.sol";
|
5
|
+
import { Bytes } from "@latticexyz/store/src/Bytes.sol";
|
6
|
+
import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol";
|
7
|
+
import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol";
|
8
|
+
import { EncodedLengths } from "@latticexyz/store/src/EncodedLengths.sol";
|
9
|
+
import { Tables } from "@latticexyz/store/src/codegen/tables/Tables.sol";
|
10
|
+
import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol";
|
11
|
+
|
12
|
+
import { ResourceId, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol";
|
13
|
+
|
14
|
+
import { MODULE_NAMESPACE } from "./constants.sol";
|
15
|
+
import { KeysWithValue } from "./tables/KeysWithValue.sol";
|
16
|
+
import { ArrayLib } from "../utils/ArrayLib.sol";
|
17
|
+
import { getTargetTableId } from "./getTargetTableId.sol";
|
18
|
+
|
19
|
+
/**
|
20
|
+
* This is a very naive and inefficient implementation for now.
|
21
|
+
* We can optimize this by adding support for `setIndexOfField` in Store
|
22
|
+
* (See https://github.com/latticexyz/mud/issues/444)
|
23
|
+
*
|
24
|
+
* Note: if a table with composite keys is used, only the first key of the tuple is indexed
|
25
|
+
*/
|
26
|
+
contract KeysWithValueHook is StoreHook {
|
27
|
+
using ArrayLib for bytes32[];
|
28
|
+
using WorldResourceIdInstance for ResourceId;
|
29
|
+
|
30
|
+
function _world() internal view returns (IBaseWorld) {
|
31
|
+
return IBaseWorld(StoreSwitch.getStoreAddress());
|
32
|
+
}
|
33
|
+
|
34
|
+
function onBeforeSetRecord(
|
35
|
+
ResourceId sourceTableId,
|
36
|
+
bytes32[] memory keyTuple,
|
37
|
+
bytes memory staticData,
|
38
|
+
EncodedLengths encodedLengths,
|
39
|
+
bytes memory dynamicData,
|
40
|
+
FieldLayout fieldLayout
|
41
|
+
) public override {
|
42
|
+
ResourceId targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId);
|
43
|
+
|
44
|
+
// Get the previous value
|
45
|
+
bytes32 previousValue = _getRecordValueHash(sourceTableId, keyTuple, fieldLayout);
|
46
|
+
|
47
|
+
// Remove the key from the list of keys with the previous value
|
48
|
+
_removeKeyFromList(targetTableId, keyTuple[0], previousValue);
|
49
|
+
|
50
|
+
// Push the key to the list of keys with the new value
|
51
|
+
bytes memory data;
|
52
|
+
if (dynamicData.length > 0) {
|
53
|
+
data = abi.encodePacked(staticData, encodedLengths, dynamicData);
|
54
|
+
} else {
|
55
|
+
data = staticData;
|
56
|
+
}
|
57
|
+
KeysWithValue.push(targetTableId, keccak256(data), keyTuple[0]);
|
58
|
+
}
|
59
|
+
|
60
|
+
function onBeforeSpliceStaticData(
|
61
|
+
ResourceId sourceTableId,
|
62
|
+
bytes32[] memory keyTuple,
|
63
|
+
uint48,
|
64
|
+
bytes memory
|
65
|
+
) public override {
|
66
|
+
// Remove the key from the list of keys with the previous value
|
67
|
+
FieldLayout fieldLayout = Tables.getFieldLayout(sourceTableId);
|
68
|
+
bytes32 previousValue = _getRecordValueHash(sourceTableId, keyTuple, fieldLayout);
|
69
|
+
ResourceId targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId);
|
70
|
+
_removeKeyFromList(targetTableId, keyTuple[0], previousValue);
|
71
|
+
}
|
72
|
+
|
73
|
+
function onAfterSpliceStaticData(
|
74
|
+
ResourceId sourceTableId,
|
75
|
+
bytes32[] memory keyTuple,
|
76
|
+
uint48,
|
77
|
+
bytes memory
|
78
|
+
) public override {
|
79
|
+
// Add the key to the list of keys with the new value
|
80
|
+
FieldLayout fieldLayout = Tables.getFieldLayout(sourceTableId);
|
81
|
+
bytes32 newValue = _getRecordValueHash(sourceTableId, keyTuple, fieldLayout);
|
82
|
+
ResourceId targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId);
|
83
|
+
KeysWithValue.push(targetTableId, newValue, keyTuple[0]);
|
84
|
+
}
|
85
|
+
|
86
|
+
function onBeforeSpliceDynamicData(
|
87
|
+
ResourceId sourceTableId,
|
88
|
+
bytes32[] memory keyTuple,
|
89
|
+
uint8,
|
90
|
+
uint40,
|
91
|
+
uint40,
|
92
|
+
EncodedLengths,
|
93
|
+
bytes memory
|
94
|
+
) public override {
|
95
|
+
// Remove the key from the list of keys with the previous value
|
96
|
+
FieldLayout fieldLayout = Tables.getFieldLayout(sourceTableId);
|
97
|
+
bytes32 previousValue = _getRecordValueHash(sourceTableId, keyTuple, fieldLayout);
|
98
|
+
ResourceId targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId);
|
99
|
+
_removeKeyFromList(targetTableId, keyTuple[0], previousValue);
|
100
|
+
}
|
101
|
+
|
102
|
+
function onAfterSpliceDynamicData(
|
103
|
+
ResourceId sourceTableId,
|
104
|
+
bytes32[] memory keyTuple,
|
105
|
+
uint8,
|
106
|
+
uint40,
|
107
|
+
uint40,
|
108
|
+
EncodedLengths,
|
109
|
+
bytes memory
|
110
|
+
) public override {
|
111
|
+
// Add the key to the list of keys with the new value
|
112
|
+
FieldLayout fieldLayout = Tables.getFieldLayout(sourceTableId);
|
113
|
+
bytes32 newValue = _getRecordValueHash(sourceTableId, keyTuple, fieldLayout);
|
114
|
+
ResourceId targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId);
|
115
|
+
KeysWithValue.push(targetTableId, newValue, keyTuple[0]);
|
116
|
+
}
|
117
|
+
|
118
|
+
function onBeforeDeleteRecord(
|
119
|
+
ResourceId sourceTableId,
|
120
|
+
bytes32[] memory keyTuple,
|
121
|
+
FieldLayout fieldLayout
|
122
|
+
) public override {
|
123
|
+
// Remove the key from the list of keys with the previous value
|
124
|
+
bytes32 previousValue = _getRecordValueHash(sourceTableId, keyTuple, fieldLayout);
|
125
|
+
ResourceId targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId);
|
126
|
+
_removeKeyFromList(targetTableId, keyTuple[0], previousValue);
|
127
|
+
}
|
128
|
+
|
129
|
+
function _getRecordValueHash(
|
130
|
+
ResourceId sourceTableId,
|
131
|
+
bytes32[] memory keyTuple,
|
132
|
+
FieldLayout fieldLayout
|
133
|
+
) internal view returns (bytes32 valueHash) {
|
134
|
+
(bytes memory staticData, EncodedLengths encodedLengths, bytes memory dynamicData) = _world().getRecord(
|
135
|
+
sourceTableId,
|
136
|
+
keyTuple,
|
137
|
+
fieldLayout
|
138
|
+
);
|
139
|
+
if (dynamicData.length > 0) {
|
140
|
+
return keccak256(abi.encodePacked(staticData, encodedLengths, dynamicData));
|
141
|
+
} else {
|
142
|
+
return keccak256(staticData);
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
function _removeKeyFromList(ResourceId targetTableId, bytes32 key, bytes32 valueHash) internal {
|
147
|
+
// Get the keys with the previous value excluding the current key
|
148
|
+
bytes32[] memory keysWithPreviousValue = KeysWithValue.get(targetTableId, valueHash).filter(key);
|
149
|
+
|
150
|
+
if (keysWithPreviousValue.length == 0) {
|
151
|
+
// Delete the list of keys in this table
|
152
|
+
KeysWithValue.deleteRecord(targetTableId, valueHash);
|
153
|
+
} else {
|
154
|
+
// Set the keys with the previous value
|
155
|
+
KeysWithValue.set(targetTableId, valueHash, keysWithPreviousValue);
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}
|
@@ -0,0 +1,103 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol";
|
4
|
+
import { BEFORE_SET_RECORD, BEFORE_SPLICE_STATIC_DATA, AFTER_SPLICE_STATIC_DATA, BEFORE_SPLICE_DYNAMIC_DATA, AFTER_SPLICE_DYNAMIC_DATA, BEFORE_DELETE_RECORD } from "@latticexyz/store/src/storeHookTypes.sol";
|
5
|
+
import { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol";
|
6
|
+
|
7
|
+
import { Module } from "@latticexyz/world/src/Module.sol";
|
8
|
+
import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol";
|
9
|
+
import { InstalledModules } from "@latticexyz/world/src/codegen/index.sol";
|
10
|
+
|
11
|
+
import { WorldContextConsumer } from "@latticexyz/world/src/WorldContext.sol";
|
12
|
+
import { ResourceId, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol";
|
13
|
+
import { revertWithBytes } from "@latticexyz/world/src/revertWithBytes.sol";
|
14
|
+
|
15
|
+
import { MODULE_NAMESPACE } from "./constants.sol";
|
16
|
+
import { KeysWithValueHook } from "./KeysWithValueHook.sol";
|
17
|
+
import { KeysWithValue } from "./tables/KeysWithValue.sol";
|
18
|
+
import { getTargetTableId } from "./getTargetTableId.sol";
|
19
|
+
|
20
|
+
/**
|
21
|
+
* This module deploys a hook that is called when a value is set in the `sourceTableId`
|
22
|
+
* provided in the install methods arguments. The hook keeps track of the keys that map to a given value.
|
23
|
+
* from value to list of keys with this value. This mapping is stored in a table registered
|
24
|
+
* by the module at the `targetTableId` provided in the install methods arguments.
|
25
|
+
*
|
26
|
+
* Note: if a table with composite keys is used, only the first key is indexed
|
27
|
+
*
|
28
|
+
* Note: this module currently only supports `installRoot` (via `World.installRootModule`).
|
29
|
+
* TODO: add support for `install` (via `World.installModule`) by using `callFrom` with the `msgSender()`
|
30
|
+
*/
|
31
|
+
contract KeysWithValueModule is Module {
|
32
|
+
using WorldResourceIdInstance for ResourceId;
|
33
|
+
|
34
|
+
// The KeysWithValueHook is deployed once and infers the target table id
|
35
|
+
// from the source table id (passed as argument to the hook methods)
|
36
|
+
KeysWithValueHook private immutable hook = new KeysWithValueHook();
|
37
|
+
|
38
|
+
function installRoot(bytes memory encodedArgs) public {
|
39
|
+
// Naive check to ensure this is only installed once
|
40
|
+
// TODO: only revert if there's nothing to do
|
41
|
+
requireNotInstalled(__self, encodedArgs);
|
42
|
+
|
43
|
+
// Extract source table id from args
|
44
|
+
ResourceId sourceTableId = ResourceId.wrap(abi.decode(encodedArgs, (bytes32)));
|
45
|
+
ResourceId targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId);
|
46
|
+
|
47
|
+
IBaseWorld world = IBaseWorld(_world());
|
48
|
+
|
49
|
+
// Register the target namespace if it doesn't exist yet
|
50
|
+
if (!ResourceIds.getExists(targetTableId.getNamespaceId())) {
|
51
|
+
(bool registrationSuccess, bytes memory registrationReturnData) = address(world).delegatecall(
|
52
|
+
abi.encodeCall(world.registerNamespace, (targetTableId.getNamespaceId()))
|
53
|
+
);
|
54
|
+
if (!registrationSuccess) revertWithBytes(registrationReturnData);
|
55
|
+
}
|
56
|
+
|
57
|
+
// Register the target table
|
58
|
+
(bool success, bytes memory returnData) = address(world).delegatecall(
|
59
|
+
abi.encodeCall(
|
60
|
+
world.registerTable,
|
61
|
+
(
|
62
|
+
targetTableId,
|
63
|
+
KeysWithValue._fieldLayout,
|
64
|
+
KeysWithValue._keySchema,
|
65
|
+
KeysWithValue._valueSchema,
|
66
|
+
KeysWithValue.getKeyNames(),
|
67
|
+
KeysWithValue.getFieldNames()
|
68
|
+
)
|
69
|
+
)
|
70
|
+
);
|
71
|
+
|
72
|
+
if (!success) revertWithBytes(returnData);
|
73
|
+
|
74
|
+
// Grant the hook access to the target table
|
75
|
+
(success, returnData) = address(world).delegatecall(
|
76
|
+
abi.encodeCall(world.grantAccess, (targetTableId, address(hook)))
|
77
|
+
);
|
78
|
+
|
79
|
+
if (!success) revertWithBytes(returnData);
|
80
|
+
|
81
|
+
// Register a hook that is called when a value is set in the source table
|
82
|
+
(success, returnData) = address(world).delegatecall(
|
83
|
+
abi.encodeCall(
|
84
|
+
world.registerStoreHook,
|
85
|
+
(
|
86
|
+
sourceTableId,
|
87
|
+
hook,
|
88
|
+
BEFORE_SET_RECORD |
|
89
|
+
BEFORE_SPLICE_STATIC_DATA |
|
90
|
+
AFTER_SPLICE_STATIC_DATA |
|
91
|
+
BEFORE_SPLICE_DYNAMIC_DATA |
|
92
|
+
AFTER_SPLICE_DYNAMIC_DATA |
|
93
|
+
BEFORE_DELETE_RECORD
|
94
|
+
)
|
95
|
+
)
|
96
|
+
);
|
97
|
+
if (!success) revertWithBytes(returnData);
|
98
|
+
}
|
99
|
+
|
100
|
+
function install(bytes memory) public pure {
|
101
|
+
revert Module_NonRootInstallNotSupported();
|
102
|
+
}
|
103
|
+
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
// Limiting the module namespace to 7 bytes so the remaining 7 bytes
|
5
|
+
// can be used for an identifier of the source table namespace to avoid
|
6
|
+
// collisions between tables with the same name in different namespaces
|
7
|
+
bytes7 constant MODULE_NAMESPACE = "keywval";
|