@latticexyz/world-modules 2.0.12-type-resolutions-effc7ab1 → 2.0.12-type-resolutions-8538f80e
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,80 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol";
|
5
|
+
import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
|
6
|
+
import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol";
|
7
|
+
import { Systems } from "@latticexyz/world/src/codegen/tables/Systems.sol";
|
8
|
+
|
9
|
+
contract Puppet {
|
10
|
+
error Puppet_AccessDenied(address caller);
|
11
|
+
|
12
|
+
IBaseWorld public immutable world;
|
13
|
+
ResourceId public immutable systemId;
|
14
|
+
|
15
|
+
constructor(IBaseWorld _world, ResourceId _systemId) {
|
16
|
+
world = _world;
|
17
|
+
systemId = _systemId;
|
18
|
+
StoreSwitch.setStoreAddress(address(_world));
|
19
|
+
}
|
20
|
+
|
21
|
+
modifier onlyPuppetMaster() {
|
22
|
+
(address systemAddress, ) = Systems.get(systemId);
|
23
|
+
if (msg.sender != systemAddress) {
|
24
|
+
revert Puppet_AccessDenied(msg.sender);
|
25
|
+
}
|
26
|
+
_;
|
27
|
+
}
|
28
|
+
|
29
|
+
fallback() external {
|
30
|
+
// Forward all calls to the system in the world
|
31
|
+
bytes memory returnData = world.callFrom(msg.sender, systemId, msg.data);
|
32
|
+
|
33
|
+
// If the call was successful, return the return data
|
34
|
+
assembly {
|
35
|
+
return(add(returnData, 0x20), mload(returnData))
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
/**
|
40
|
+
* @dev Log an event with a signature and no additional topic
|
41
|
+
*/
|
42
|
+
function log(bytes32 eventSignature, bytes memory eventData) public onlyPuppetMaster {
|
43
|
+
assembly {
|
44
|
+
log1(add(eventData, 0x20), mload(eventData), eventSignature)
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
/**
|
49
|
+
* @dev Log an event with a signature and one additional topics
|
50
|
+
*/
|
51
|
+
function log(bytes32 eventSignature, bytes32 topic1, bytes memory eventData) public onlyPuppetMaster {
|
52
|
+
assembly {
|
53
|
+
log2(add(eventData, 0x20), mload(eventData), eventSignature, topic1)
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
/**
|
58
|
+
* @dev Log an event with a signature and two additional topics
|
59
|
+
*/
|
60
|
+
function log(bytes32 eventSignature, bytes32 topic1, bytes32 topic2, bytes memory eventData) public onlyPuppetMaster {
|
61
|
+
assembly {
|
62
|
+
log3(add(eventData, 0x20), mload(eventData), eventSignature, topic1, topic2)
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
/**
|
67
|
+
* @dev Log an event with a signature and three additional topics
|
68
|
+
*/
|
69
|
+
function log(
|
70
|
+
bytes32 eventSignature,
|
71
|
+
bytes32 topic1,
|
72
|
+
bytes32 topic2,
|
73
|
+
bytes32 topic3,
|
74
|
+
bytes memory eventData
|
75
|
+
) public onlyPuppetMaster {
|
76
|
+
assembly {
|
77
|
+
log4(add(eventData, 0x20), mload(eventData), eventSignature, topic1, topic2, topic3)
|
78
|
+
}
|
79
|
+
}
|
80
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
import { DelegationControl } from "@latticexyz/world/src/DelegationControl.sol";
|
5
|
+
import { ResourceId } from "@latticexyz/world/src/WorldResourceId.sol";
|
6
|
+
import { PuppetRegistry } from "./tables/PuppetRegistry.sol";
|
7
|
+
import { PUPPET_TABLE_ID } from "./constants.sol";
|
8
|
+
|
9
|
+
contract PuppetDelegationControl is DelegationControl {
|
10
|
+
/**
|
11
|
+
* Verify a delegation by checking if the resourceId maps to the caller as puppet
|
12
|
+
*/
|
13
|
+
function verify(address, ResourceId systemId, bytes memory) public view returns (bool) {
|
14
|
+
address puppet = _msgSender();
|
15
|
+
return PuppetRegistry.get(PUPPET_TABLE_ID, systemId) == puppet;
|
16
|
+
}
|
17
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
|
5
|
+
import { System } from "@latticexyz/world/src/System.sol";
|
6
|
+
import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol";
|
7
|
+
|
8
|
+
import { AccessControlLib } from "../../utils/AccessControlLib.sol";
|
9
|
+
|
10
|
+
import { PuppetRegistry } from "./tables/PuppetRegistry.sol";
|
11
|
+
import { Puppet } from "./Puppet.sol";
|
12
|
+
import { PUPPET_TABLE_ID } from "./constants.sol";
|
13
|
+
|
14
|
+
contract PuppetFactorySystem is System {
|
15
|
+
function createPuppet(ResourceId systemId) public returns (address puppet) {
|
16
|
+
// Only the owner of a system can create a puppet for it
|
17
|
+
AccessControlLib.requireOwner(systemId, _msgSender());
|
18
|
+
|
19
|
+
// Deploy a new puppet contract
|
20
|
+
puppet = address(new Puppet(IBaseWorld(_world()), systemId));
|
21
|
+
|
22
|
+
// Register the puppet
|
23
|
+
PuppetRegistry.set(PUPPET_TABLE_ID, systemId, puppet);
|
24
|
+
}
|
25
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
|
5
|
+
import { SystemRegistry } from "@latticexyz/world/src/codegen/tables/SystemRegistry.sol";
|
6
|
+
import { PuppetRegistry } from "./tables/PuppetRegistry.sol";
|
7
|
+
import { PUPPET_TABLE_ID } from "./constants.sol";
|
8
|
+
import { Puppet } from "./Puppet.sol";
|
9
|
+
|
10
|
+
contract PuppetMaster {
|
11
|
+
error PuppetMaster_NoPuppet(address systemAddress, ResourceId systemId);
|
12
|
+
|
13
|
+
function puppet() internal view returns (Puppet) {
|
14
|
+
ResourceId systemId = SystemRegistry.getSystemId(address(this));
|
15
|
+
address puppetAddress = PuppetRegistry.get(PUPPET_TABLE_ID, systemId);
|
16
|
+
if (puppetAddress == address(0)) revert PuppetMaster_NoPuppet(address(this), systemId);
|
17
|
+
return Puppet(puppetAddress);
|
18
|
+
}
|
19
|
+
}
|
@@ -0,0 +1,64 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol";
|
5
|
+
import { Module } from "@latticexyz/world/src/Module.sol";
|
6
|
+
import { revertWithBytes } from "@latticexyz/world/src/revertWithBytes.sol";
|
7
|
+
import { WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol";
|
8
|
+
|
9
|
+
import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
|
10
|
+
|
11
|
+
import { PuppetFactorySystem } from "./PuppetFactorySystem.sol";
|
12
|
+
import { PuppetDelegationControl } from "./PuppetDelegationControl.sol";
|
13
|
+
import { PUPPET_DELEGATION, PUPPET_FACTORY, PUPPET_TABLE_ID, NAMESPACE_ID } from "./constants.sol";
|
14
|
+
|
15
|
+
import { PuppetRegistry } from "./tables/PuppetRegistry.sol";
|
16
|
+
|
17
|
+
/**
|
18
|
+
* This module registers tables and delegation control systems required for puppet delegations
|
19
|
+
*/
|
20
|
+
contract PuppetModule is Module {
|
21
|
+
using WorldResourceIdInstance for ResourceId;
|
22
|
+
|
23
|
+
PuppetDelegationControl private immutable puppetDelegationControl = new PuppetDelegationControl();
|
24
|
+
PuppetFactorySystem private immutable puppetFactorySystem = new PuppetFactorySystem();
|
25
|
+
|
26
|
+
function installRoot(bytes memory) public {
|
27
|
+
IBaseWorld world = IBaseWorld(_world());
|
28
|
+
|
29
|
+
// Register namespace
|
30
|
+
(bool success, bytes memory returnData) = address(world).delegatecall(
|
31
|
+
abi.encodeCall(world.registerNamespace, (NAMESPACE_ID))
|
32
|
+
);
|
33
|
+
if (!success) revertWithBytes(returnData);
|
34
|
+
|
35
|
+
// Register table
|
36
|
+
PuppetRegistry.register(PUPPET_TABLE_ID);
|
37
|
+
|
38
|
+
// Register puppet factory
|
39
|
+
(success, returnData) = address(world).delegatecall(
|
40
|
+
abi.encodeCall(world.registerSystem, (PUPPET_FACTORY, puppetFactorySystem, true))
|
41
|
+
);
|
42
|
+
if (!success) revertWithBytes(returnData);
|
43
|
+
|
44
|
+
// Register puppet delegation control
|
45
|
+
(success, returnData) = address(world).delegatecall(
|
46
|
+
abi.encodeCall(world.registerSystem, (PUPPET_DELEGATION, puppetDelegationControl, true))
|
47
|
+
);
|
48
|
+
if (!success) revertWithBytes(returnData);
|
49
|
+
}
|
50
|
+
|
51
|
+
function install(bytes memory) public {
|
52
|
+
IBaseWorld world = IBaseWorld(_world());
|
53
|
+
|
54
|
+
// Register namespace
|
55
|
+
world.registerNamespace(NAMESPACE_ID);
|
56
|
+
|
57
|
+
// Register table
|
58
|
+
PuppetRegistry.register(PUPPET_TABLE_ID);
|
59
|
+
|
60
|
+
// Register puppet factory and delegation control
|
61
|
+
world.registerSystem(PUPPET_FACTORY, puppetFactorySystem, true);
|
62
|
+
world.registerSystem(PUPPET_DELEGATION, puppetDelegationControl, true);
|
63
|
+
}
|
64
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
|
5
|
+
import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol";
|
6
|
+
import { RESOURCE_SYSTEM, RESOURCE_NAMESPACE } from "@latticexyz/world/src/worldResourceTypes.sol";
|
7
|
+
import { ROOT_NAMESPACE } from "@latticexyz/world/src/constants.sol";
|
8
|
+
|
9
|
+
bytes14 constant NAMESPACE = bytes14("puppet");
|
10
|
+
|
11
|
+
ResourceId constant NAMESPACE_ID = ResourceId.wrap(bytes32(abi.encodePacked(RESOURCE_NAMESPACE, NAMESPACE)));
|
12
|
+
|
13
|
+
ResourceId constant PUPPET_DELEGATION = ResourceId.wrap(
|
14
|
+
bytes32(abi.encodePacked(RESOURCE_SYSTEM, NAMESPACE, bytes16("Delegation")))
|
15
|
+
);
|
16
|
+
|
17
|
+
ResourceId constant PUPPET_FACTORY = ResourceId.wrap(
|
18
|
+
bytes32(abi.encodePacked(RESOURCE_SYSTEM, NAMESPACE, bytes16("Factory")))
|
19
|
+
);
|
20
|
+
|
21
|
+
ResourceId constant PUPPET_TABLE_ID = ResourceId.wrap(
|
22
|
+
bytes32(abi.encodePacked(RESOURCE_TABLE, NAMESPACE, bytes16("PuppetRegistry")))
|
23
|
+
);
|
@@ -0,0 +1,24 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
|
5
|
+
import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol";
|
6
|
+
import { WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol";
|
7
|
+
import { PUPPET_DELEGATION, PUPPET_FACTORY } from "./constants.sol";
|
8
|
+
import { PuppetDelegationControl } from "./PuppetDelegationControl.sol";
|
9
|
+
import { Puppet } from "./Puppet.sol";
|
10
|
+
import { PuppetFactorySystem } from "./PuppetFactorySystem.sol";
|
11
|
+
|
12
|
+
using WorldResourceIdInstance for ResourceId;
|
13
|
+
|
14
|
+
/**
|
15
|
+
* This free function can be used to create a puppet and register it with the puppet delegation control.
|
16
|
+
* Since it is inlined in the caller's context, the calls originate from the caller's address.
|
17
|
+
*/
|
18
|
+
function createPuppet(IBaseWorld world, ResourceId systemId) returns (address puppet) {
|
19
|
+
puppet = abi.decode(
|
20
|
+
world.call(PUPPET_FACTORY, abi.encodeCall(PuppetFactorySystem.createPuppet, (systemId))),
|
21
|
+
(address)
|
22
|
+
);
|
23
|
+
world.registerNamespaceDelegation(systemId.getNamespaceId(), PUPPET_DELEGATION, new bytes(0));
|
24
|
+
}
|
@@ -0,0 +1,199 @@
|
|
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 PuppetRegistry {
|
23
|
+
FieldLayout constant _fieldLayout =
|
24
|
+
FieldLayout.wrap(0x0014010014000000000000000000000000000000000000000000000000000000);
|
25
|
+
|
26
|
+
// Hex-encoded key schema of (bytes32)
|
27
|
+
Schema constant _keySchema = Schema.wrap(0x002001005f000000000000000000000000000000000000000000000000000000);
|
28
|
+
// Hex-encoded value schema of (address)
|
29
|
+
Schema constant _valueSchema = Schema.wrap(0x0014010061000000000000000000000000000000000000000000000000000000);
|
30
|
+
|
31
|
+
/**
|
32
|
+
* @notice Get the table's key field names.
|
33
|
+
* @return keyNames An array of strings with the names of key fields.
|
34
|
+
*/
|
35
|
+
function getKeyNames() internal pure returns (string[] memory keyNames) {
|
36
|
+
keyNames = new string[](1);
|
37
|
+
keyNames[0] = "systemId";
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* @notice Get the table's value field names.
|
42
|
+
* @return fieldNames An array of strings with the names of value fields.
|
43
|
+
*/
|
44
|
+
function getFieldNames() internal pure returns (string[] memory fieldNames) {
|
45
|
+
fieldNames = new string[](1);
|
46
|
+
fieldNames[0] = "puppet";
|
47
|
+
}
|
48
|
+
|
49
|
+
/**
|
50
|
+
* @notice Register the table with its config.
|
51
|
+
*/
|
52
|
+
function register(ResourceId _tableId) internal {
|
53
|
+
StoreSwitch.registerTable(_tableId, _fieldLayout, _keySchema, _valueSchema, getKeyNames(), getFieldNames());
|
54
|
+
}
|
55
|
+
|
56
|
+
/**
|
57
|
+
* @notice Register the table with its config.
|
58
|
+
*/
|
59
|
+
function _register(ResourceId _tableId) internal {
|
60
|
+
StoreCore.registerTable(_tableId, _fieldLayout, _keySchema, _valueSchema, getKeyNames(), getFieldNames());
|
61
|
+
}
|
62
|
+
|
63
|
+
/**
|
64
|
+
* @notice Get puppet.
|
65
|
+
*/
|
66
|
+
function getPuppet(ResourceId _tableId, ResourceId systemId) internal view returns (address puppet) {
|
67
|
+
bytes32[] memory _keyTuple = new bytes32[](1);
|
68
|
+
_keyTuple[0] = ResourceId.unwrap(systemId);
|
69
|
+
|
70
|
+
bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout);
|
71
|
+
return (address(bytes20(_blob)));
|
72
|
+
}
|
73
|
+
|
74
|
+
/**
|
75
|
+
* @notice Get puppet.
|
76
|
+
*/
|
77
|
+
function _getPuppet(ResourceId _tableId, ResourceId systemId) internal view returns (address puppet) {
|
78
|
+
bytes32[] memory _keyTuple = new bytes32[](1);
|
79
|
+
_keyTuple[0] = ResourceId.unwrap(systemId);
|
80
|
+
|
81
|
+
bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout);
|
82
|
+
return (address(bytes20(_blob)));
|
83
|
+
}
|
84
|
+
|
85
|
+
/**
|
86
|
+
* @notice Get puppet.
|
87
|
+
*/
|
88
|
+
function get(ResourceId _tableId, ResourceId systemId) internal view returns (address puppet) {
|
89
|
+
bytes32[] memory _keyTuple = new bytes32[](1);
|
90
|
+
_keyTuple[0] = ResourceId.unwrap(systemId);
|
91
|
+
|
92
|
+
bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout);
|
93
|
+
return (address(bytes20(_blob)));
|
94
|
+
}
|
95
|
+
|
96
|
+
/**
|
97
|
+
* @notice Get puppet.
|
98
|
+
*/
|
99
|
+
function _get(ResourceId _tableId, ResourceId systemId) internal view returns (address puppet) {
|
100
|
+
bytes32[] memory _keyTuple = new bytes32[](1);
|
101
|
+
_keyTuple[0] = ResourceId.unwrap(systemId);
|
102
|
+
|
103
|
+
bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout);
|
104
|
+
return (address(bytes20(_blob)));
|
105
|
+
}
|
106
|
+
|
107
|
+
/**
|
108
|
+
* @notice Set puppet.
|
109
|
+
*/
|
110
|
+
function setPuppet(ResourceId _tableId, ResourceId systemId, address puppet) internal {
|
111
|
+
bytes32[] memory _keyTuple = new bytes32[](1);
|
112
|
+
_keyTuple[0] = ResourceId.unwrap(systemId);
|
113
|
+
|
114
|
+
StoreSwitch.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((puppet)), _fieldLayout);
|
115
|
+
}
|
116
|
+
|
117
|
+
/**
|
118
|
+
* @notice Set puppet.
|
119
|
+
*/
|
120
|
+
function _setPuppet(ResourceId _tableId, ResourceId systemId, address puppet) internal {
|
121
|
+
bytes32[] memory _keyTuple = new bytes32[](1);
|
122
|
+
_keyTuple[0] = ResourceId.unwrap(systemId);
|
123
|
+
|
124
|
+
StoreCore.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((puppet)), _fieldLayout);
|
125
|
+
}
|
126
|
+
|
127
|
+
/**
|
128
|
+
* @notice Set puppet.
|
129
|
+
*/
|
130
|
+
function set(ResourceId _tableId, ResourceId systemId, address puppet) internal {
|
131
|
+
bytes32[] memory _keyTuple = new bytes32[](1);
|
132
|
+
_keyTuple[0] = ResourceId.unwrap(systemId);
|
133
|
+
|
134
|
+
StoreSwitch.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((puppet)), _fieldLayout);
|
135
|
+
}
|
136
|
+
|
137
|
+
/**
|
138
|
+
* @notice Set puppet.
|
139
|
+
*/
|
140
|
+
function _set(ResourceId _tableId, ResourceId systemId, address puppet) internal {
|
141
|
+
bytes32[] memory _keyTuple = new bytes32[](1);
|
142
|
+
_keyTuple[0] = ResourceId.unwrap(systemId);
|
143
|
+
|
144
|
+
StoreCore.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((puppet)), _fieldLayout);
|
145
|
+
}
|
146
|
+
|
147
|
+
/**
|
148
|
+
* @notice Delete all data for given keys.
|
149
|
+
*/
|
150
|
+
function deleteRecord(ResourceId _tableId, ResourceId systemId) internal {
|
151
|
+
bytes32[] memory _keyTuple = new bytes32[](1);
|
152
|
+
_keyTuple[0] = ResourceId.unwrap(systemId);
|
153
|
+
|
154
|
+
StoreSwitch.deleteRecord(_tableId, _keyTuple);
|
155
|
+
}
|
156
|
+
|
157
|
+
/**
|
158
|
+
* @notice Delete all data for given keys.
|
159
|
+
*/
|
160
|
+
function _deleteRecord(ResourceId _tableId, ResourceId systemId) internal {
|
161
|
+
bytes32[] memory _keyTuple = new bytes32[](1);
|
162
|
+
_keyTuple[0] = ResourceId.unwrap(systemId);
|
163
|
+
|
164
|
+
StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout);
|
165
|
+
}
|
166
|
+
|
167
|
+
/**
|
168
|
+
* @notice Tightly pack static (fixed length) data using this table's schema.
|
169
|
+
* @return The static data, encoded into a sequence of bytes.
|
170
|
+
*/
|
171
|
+
function encodeStatic(address puppet) internal pure returns (bytes memory) {
|
172
|
+
return abi.encodePacked(puppet);
|
173
|
+
}
|
174
|
+
|
175
|
+
/**
|
176
|
+
* @notice Encode all of a record's fields.
|
177
|
+
* @return The static (fixed length) data, encoded into a sequence of bytes.
|
178
|
+
* @return The lengths of the dynamic fields (packed into a single bytes32 value).
|
179
|
+
* @return The dynamic (variable length) data, encoded into a sequence of bytes.
|
180
|
+
*/
|
181
|
+
function encode(address puppet) internal pure returns (bytes memory, EncodedLengths, bytes memory) {
|
182
|
+
bytes memory _staticData = encodeStatic(puppet);
|
183
|
+
|
184
|
+
EncodedLengths _encodedLengths;
|
185
|
+
bytes memory _dynamicData;
|
186
|
+
|
187
|
+
return (_staticData, _encodedLengths, _dynamicData);
|
188
|
+
}
|
189
|
+
|
190
|
+
/**
|
191
|
+
* @notice Encode keys as a bytes32 array using this table's field layout.
|
192
|
+
*/
|
193
|
+
function encodeKeyTuple(ResourceId systemId) internal pure returns (bytes32[] memory) {
|
194
|
+
bytes32[] memory _keyTuple = new bytes32[](1);
|
195
|
+
_keyTuple[0] = ResourceId.unwrap(systemId);
|
196
|
+
|
197
|
+
return _keyTuple;
|
198
|
+
}
|
199
|
+
}
|
@@ -0,0 +1,64 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
import { DelegationControl } from "@latticexyz/world/src/DelegationControl.sol";
|
5
|
+
import { ResourceId } from "@latticexyz/world/src/WorldResourceId.sol";
|
6
|
+
import { CallboundDelegations } from "./tables/CallboundDelegations.sol";
|
7
|
+
|
8
|
+
contract CallboundDelegationControl is DelegationControl {
|
9
|
+
/**
|
10
|
+
* Verify a delegation by checking if the delegator has any available calls left in the CallboundDelegations table and decrementing the available calls if so.
|
11
|
+
*/
|
12
|
+
function verify(address delegator, ResourceId systemId, bytes memory callData) public returns (bool) {
|
13
|
+
bytes32 callDataHash = keccak256(callData);
|
14
|
+
|
15
|
+
// Get the number of available calls for the given delegator, systemId and callData
|
16
|
+
uint256 availableCalls = CallboundDelegations.get({
|
17
|
+
delegator: delegator,
|
18
|
+
delegatee: _msgSender(),
|
19
|
+
systemId: systemId,
|
20
|
+
callDataHash: callDataHash
|
21
|
+
});
|
22
|
+
|
23
|
+
if (availableCalls == 1) {
|
24
|
+
// Remove the delegation from the CallboundDelegations table
|
25
|
+
CallboundDelegations.deleteRecord({
|
26
|
+
delegator: delegator,
|
27
|
+
delegatee: _msgSender(),
|
28
|
+
systemId: systemId,
|
29
|
+
callDataHash: callDataHash
|
30
|
+
});
|
31
|
+
return true;
|
32
|
+
}
|
33
|
+
|
34
|
+
if (availableCalls > 0) {
|
35
|
+
// Decrement the number of available calls
|
36
|
+
unchecked {
|
37
|
+
availableCalls--;
|
38
|
+
}
|
39
|
+
CallboundDelegations.set({
|
40
|
+
delegator: delegator,
|
41
|
+
delegatee: _msgSender(),
|
42
|
+
systemId: systemId,
|
43
|
+
callDataHash: callDataHash,
|
44
|
+
availableCalls: availableCalls
|
45
|
+
});
|
46
|
+
return true;
|
47
|
+
}
|
48
|
+
|
49
|
+
return false;
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Initialize a delegation by setting the number of available calls in the CallboundDelegations table
|
54
|
+
*/
|
55
|
+
function initDelegation(address delegatee, ResourceId systemId, bytes memory callData, uint256 numCalls) public {
|
56
|
+
CallboundDelegations.set({
|
57
|
+
delegator: _msgSender(),
|
58
|
+
delegatee: delegatee,
|
59
|
+
systemId: systemId,
|
60
|
+
callDataHash: keccak256(callData),
|
61
|
+
availableCalls: numCalls
|
62
|
+
});
|
63
|
+
}
|
64
|
+
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol";
|
5
|
+
|
6
|
+
import { Module } from "@latticexyz/world/src/Module.sol";
|
7
|
+
import { WorldContextConsumer } from "@latticexyz/world/src/WorldContext.sol";
|
8
|
+
import { revertWithBytes } from "@latticexyz/world/src/revertWithBytes.sol";
|
9
|
+
|
10
|
+
import { CallboundDelegationControl } from "./CallboundDelegationControl.sol";
|
11
|
+
import { SystemboundDelegationControl } from "./SystemboundDelegationControl.sol";
|
12
|
+
import { TimeboundDelegationControl } from "./TimeboundDelegationControl.sol";
|
13
|
+
import { CALLBOUND_DELEGATION, SYSTEMBOUND_DELEGATION, TIMEBOUND_DELEGATION } from "./constants.sol";
|
14
|
+
|
15
|
+
import { CallboundDelegations } from "./tables/CallboundDelegations.sol";
|
16
|
+
import { SystemboundDelegations } from "./tables/SystemboundDelegations.sol";
|
17
|
+
import { TimeboundDelegations } from "./tables/TimeboundDelegations.sol";
|
18
|
+
|
19
|
+
/**
|
20
|
+
* This module registers tables and delegation control systems required for standard delegations
|
21
|
+
*/
|
22
|
+
contract StandardDelegationsModule is Module {
|
23
|
+
CallboundDelegationControl private immutable callboundDelegationControl = new CallboundDelegationControl();
|
24
|
+
SystemboundDelegationControl private immutable systemboundDelegationControl = new SystemboundDelegationControl();
|
25
|
+
TimeboundDelegationControl private immutable timeboundDelegationControl = new TimeboundDelegationControl();
|
26
|
+
|
27
|
+
function installRoot(bytes memory) public {
|
28
|
+
IBaseWorld world = IBaseWorld(_world());
|
29
|
+
|
30
|
+
// Register tables
|
31
|
+
CallboundDelegations.register();
|
32
|
+
SystemboundDelegations.register();
|
33
|
+
TimeboundDelegations.register();
|
34
|
+
|
35
|
+
// Register systems
|
36
|
+
(bool success, bytes memory returnData) = address(world).delegatecall(
|
37
|
+
abi.encodeCall(world.registerSystem, (CALLBOUND_DELEGATION, callboundDelegationControl, true))
|
38
|
+
);
|
39
|
+
if (!success) revertWithBytes(returnData);
|
40
|
+
|
41
|
+
(success, returnData) = address(world).delegatecall(
|
42
|
+
abi.encodeCall(world.registerSystem, (SYSTEMBOUND_DELEGATION, systemboundDelegationControl, true))
|
43
|
+
);
|
44
|
+
if (!success) revertWithBytes(returnData);
|
45
|
+
|
46
|
+
(success, returnData) = address(world).delegatecall(
|
47
|
+
abi.encodeCall(world.registerSystem, (TIMEBOUND_DELEGATION, timeboundDelegationControl, true))
|
48
|
+
);
|
49
|
+
if (!success) revertWithBytes(returnData);
|
50
|
+
}
|
51
|
+
|
52
|
+
function install(bytes memory) public pure {
|
53
|
+
revert Module_NonRootInstallNotSupported();
|
54
|
+
}
|
55
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
import { DelegationControl } from "@latticexyz/world/src/DelegationControl.sol";
|
5
|
+
import { ResourceId } from "@latticexyz/world/src/WorldResourceId.sol";
|
6
|
+
import { SystemboundDelegations } from "./tables/SystemboundDelegations.sol";
|
7
|
+
|
8
|
+
contract SystemboundDelegationControl is DelegationControl {
|
9
|
+
/**
|
10
|
+
* Verify a delegation by checking if the caller (delegatee) has any available calls left for the given delegator in the SystemboundDelegations table and decrementing the available calls if so.
|
11
|
+
*/
|
12
|
+
function verify(address delegator, ResourceId systemId, bytes memory) public returns (bool) {
|
13
|
+
// Get the number of available calls for the given delegator, systemId and callData
|
14
|
+
uint256 availableCalls = SystemboundDelegations.get({
|
15
|
+
delegator: delegator,
|
16
|
+
delegatee: _msgSender(),
|
17
|
+
systemId: systemId
|
18
|
+
});
|
19
|
+
|
20
|
+
if (availableCalls == 1) {
|
21
|
+
// Remove the delegation from the SystemboundDelegations table
|
22
|
+
SystemboundDelegations.deleteRecord({ delegator: delegator, delegatee: _msgSender(), systemId: systemId });
|
23
|
+
return true;
|
24
|
+
}
|
25
|
+
|
26
|
+
if (availableCalls > 0) {
|
27
|
+
// Decrement the number of available calls
|
28
|
+
unchecked {
|
29
|
+
availableCalls--;
|
30
|
+
}
|
31
|
+
SystemboundDelegations.set({
|
32
|
+
delegator: delegator,
|
33
|
+
delegatee: _msgSender(),
|
34
|
+
systemId: systemId,
|
35
|
+
availableCalls: availableCalls
|
36
|
+
});
|
37
|
+
return true;
|
38
|
+
}
|
39
|
+
|
40
|
+
return false;
|
41
|
+
}
|
42
|
+
|
43
|
+
/**
|
44
|
+
* Initialize a delegation by setting the number of available calls in the SystemboundDelegations table
|
45
|
+
*/
|
46
|
+
function initDelegation(address delegatee, ResourceId systemId, uint256 numCalls) public {
|
47
|
+
SystemboundDelegations.set({
|
48
|
+
delegator: _msgSender(),
|
49
|
+
delegatee: delegatee,
|
50
|
+
systemId: systemId,
|
51
|
+
availableCalls: numCalls
|
52
|
+
});
|
53
|
+
}
|
54
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
2
|
+
pragma solidity >=0.8.24;
|
3
|
+
|
4
|
+
import { DelegationControl } from "@latticexyz/world/src/DelegationControl.sol";
|
5
|
+
import { ResourceId } from "@latticexyz/world/src/WorldResourceId.sol";
|
6
|
+
import { TimeboundDelegations } from "./tables/TimeboundDelegations.sol";
|
7
|
+
|
8
|
+
contract TimeboundDelegationControl is DelegationControl {
|
9
|
+
/**
|
10
|
+
* Verify a delegation by checking if the current block timestamp is not larger than the max valid timestamp for the delegation.
|
11
|
+
* Note: the delegation control check ignores the systemId and callData parameters.
|
12
|
+
*/
|
13
|
+
function verify(address delegator, ResourceId, bytes memory) public view returns (bool) {
|
14
|
+
// Get the max valid timestamp for the given delegator
|
15
|
+
uint256 maxTimestamp = TimeboundDelegations.get({ delegator: delegator, delegatee: _msgSender() });
|
16
|
+
|
17
|
+
// Return true if the current timestamp is smaller or equal to the max valid timestamp
|
18
|
+
return block.timestamp <= maxTimestamp;
|
19
|
+
}
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Initialize a delegation by setting the max valid timestamp in the TimeboundDelegations table
|
23
|
+
*/
|
24
|
+
function initDelegation(address delegatee, uint256 maxTimestamp) public {
|
25
|
+
TimeboundDelegations.set({ delegator: _msgSender(), delegatee: delegatee, maxTimestamp: maxTimestamp });
|
26
|
+
}
|
27
|
+
}
|