/
ERC20Module.sol
93 lines (74 loc) · 3.53 KB
/
ERC20Module.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.21;
import { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol";
import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
import { Module } from "@latticexyz/world/src/Module.sol";
import { WorldResourceIdLib } from "@latticexyz/world/src/WorldResourceId.sol";
import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol";
import { InstalledModules } from "@latticexyz/world/src/codegen/tables/InstalledModules.sol";
import { Puppet } from "../puppet/Puppet.sol";
import { createPuppet } from "../puppet/createPuppet.sol";
import { MODULE_NAME as PUPPET_MODULE_NAME } from "../puppet/constants.sol";
import { MODULE_NAME, MODULE_NAMESPACE, MODULE_NAMESPACE_ID, ERC20_REGISTRY_TABLE_ID } from "./constants.sol";
import { _allowancesTableId, _balancesTableId, _metadataTableId, _erc20SystemId } from "./utils.sol";
import { ERC20System } from "./ERC20System.sol";
import { ERC20Registry } from "./tables/ERC20Registry.sol";
import { Balances } from "./tables/Balances.sol";
import { Allowances } from "./tables/Allowances.sol";
import { Metadata, MetadataData } from "./tables/Metadata.sol";
contract ERC20Module is Module {
error ERC20Module_InvalidNamespace(bytes14 namespace);
function getName() public pure override returns (bytes16) {
return MODULE_NAME;
}
/**
* Register systems and tables for a new ERC20 token in a given namespace
*/
function _registerERC20(bytes14 namespace) internal {
// Register the tables
Allowances.register(_allowancesTableId(namespace));
Balances.register(_balancesTableId(namespace));
Metadata.register(_metadataTableId(namespace));
// Register a new ERC20System
IBaseWorld(_world()).registerSystem(_erc20SystemId(namespace), new ERC20System(), true);
}
function _requireDependencies() internal view {
// If the PuppetModule is not installed yet, install it
if (InstalledModules.get(PUPPET_MODULE_NAME, keccak256(new bytes(0))) == address(0)) {
revert Module_MissingDependency(string(bytes.concat(PUPPET_MODULE_NAME)));
}
}
function install(bytes memory args) public {
// Require the module to not be installed with these args yet
if (InstalledModules.get(MODULE_NAME, keccak256(args)) != address(0)) {
revert Module_AlreadyInstalled();
}
// Extract args
(bytes14 namespace, MetadataData memory metadata) = abi.decode(args, (bytes14, MetadataData));
// Require the namespace to not be the module's namespace
if (namespace == MODULE_NAMESPACE) {
revert ERC20Module_InvalidNamespace(namespace);
}
// Require dependencies
_requireDependencies();
// Register the ERC20 tables and system
_registerERC20(namespace);
// Initialize the Metadata
Metadata.set(_metadataTableId(namespace), metadata);
// Deploy and register the ERC20 puppet.
IBaseWorld world = IBaseWorld(_world());
ResourceId erc20SystemId = _erc20SystemId(namespace);
address puppet = createPuppet(erc20SystemId);
// Transfer ownership of the namespace to the caller
ResourceId namespaceId = WorldResourceIdLib.encodeNamespace(namespace);
world.transferOwnership(namespaceId, _msgSender());
// Register the ERC20 in the ERC20Registry
if (!ResourceIds.getExists(ERC20_REGISTRY_TABLE_ID)) {
ERC20Registry.register(ERC20_REGISTRY_TABLE_ID);
}
ERC20Registry.set(ERC20_REGISTRY_TABLE_ID, namespaceId, puppet);
}
function installRoot(bytes memory) public pure {
revert Module_RootInstallNotSupported();
}
}