@towns-protocol/contracts 0.0.383 → 0.0.385
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/package.json +3 -3
- package/scripts/deployments/diamonds/DeployAppRegistry.s.sol +22 -15
- package/scripts/deployments/diamonds/DeploySimpleAppBeacon.s.sol +149 -0
- package/scripts/deployments/diamonds/DeploySpaceFactory.s.sol +0 -1
- package/scripts/deployments/facets/DeployAppFactoryFacet.s.sol +14 -3
- package/scripts/interactions/InteractRegisterApp.s.sol +0 -1
- package/scripts/interactions/diamonds/InteractAppRegistry.s.sol +75 -0
- package/src/apps/BaseApp.sol +9 -6
- package/src/apps/ITownsApp.sol +4 -0
- package/src/apps/facets/factory/AppFactoryBase.sol +108 -0
- package/src/apps/facets/factory/AppFactoryFacet.sol +55 -19
- package/src/apps/facets/factory/AppFactoryStorage.sol +29 -0
- package/src/apps/facets/factory/IAppFactory.sol +46 -0
- package/src/apps/facets/registry/AppRegistryBase.sol +7 -20
- package/src/apps/facets/registry/IAppRegistry.sol +3 -2
- package/src/apps/facets/registry/LibAppRegistry.sol +33 -0
- package/src/apps/simple/account/ISimpleAccount.sol +40 -0
- package/src/apps/simple/account/SimpleAccountBase.sol +58 -0
- package/src/apps/simple/account/SimpleAccountFacet.sol +151 -0
- package/src/apps/simple/account/SimpleAccountStorage.sol +25 -0
- package/src/apps/{helpers → simple/app}/ISimpleApp.sol +20 -27
- package/src/apps/simple/app/SimpleAppFacet.sol +202 -0
- package/src/apps/{helpers → simple/app}/SimpleAppStorage.sol +1 -1
- package/scripts/deployments/facets/DeploySimpleApp.s.sol +0 -10
- package/src/apps/helpers/SimpleApp.sol +0 -123
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@towns-protocol/contracts",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.385",
|
|
4
4
|
"packageManager": "yarn@3.8.0",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build-types": "bash scripts/build-contract-types.sh",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@layerzerolabs/oapp-evm": "^0.3.2",
|
|
36
36
|
"@openzeppelin/merkle-tree": "^1.0.8",
|
|
37
37
|
"@prb/test": "^0.6.4",
|
|
38
|
-
"@towns-protocol/prettier-config": "^0.0.
|
|
38
|
+
"@towns-protocol/prettier-config": "^0.0.385",
|
|
39
39
|
"@typechain/ethers-v5": "^11.1.2",
|
|
40
40
|
"@wagmi/cli": "^2.2.0",
|
|
41
41
|
"forge-std": "github:foundry-rs/forge-std#v1.10.0",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"publishConfig": {
|
|
58
58
|
"access": "public"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "2b60b355cb85529d292b3702a695750f5c884ab7"
|
|
61
61
|
}
|
|
@@ -3,6 +3,7 @@ pragma solidity ^0.8.23;
|
|
|
3
3
|
|
|
4
4
|
// interfaces
|
|
5
5
|
import {IDiamondInitHelper} from "./IDiamondInitHelper.sol";
|
|
6
|
+
import {IAppFactory, IAppFactoryBase} from "src/apps/facets/factory/IAppFactory.sol";
|
|
6
7
|
|
|
7
8
|
// libraries
|
|
8
9
|
import {DeployDiamondCut} from "@towns-protocol/diamond/scripts/deployments/facets/DeployDiamondCut.sol";
|
|
@@ -12,15 +13,16 @@ import {DeployOwnable} from "@towns-protocol/diamond/scripts/deployments/facets/
|
|
|
12
13
|
import {LibString} from "solady/utils/LibString.sol";
|
|
13
14
|
import {DeployMetadata} from "../facets/DeployMetadata.s.sol";
|
|
14
15
|
import {DeployAppRegistryFacet} from "../facets/DeployAppRegistryFacet.s.sol";
|
|
15
|
-
import {DeployUpgradeableBeacon} from "../facets/DeployUpgradeableBeacon.s.sol";
|
|
16
16
|
import {DeployAppInstallerFacet} from "../facets/DeployAppInstallerFacet.s.sol";
|
|
17
17
|
import {DeployAppFactoryFacet} from "../facets/DeployAppFactoryFacet.s.sol";
|
|
18
18
|
import {DeploySpaceFactory} from "../diamonds/DeploySpaceFactory.s.sol";
|
|
19
|
+
import {DeploySimpleAppBeacon} from "../diamonds/DeploySimpleAppBeacon.s.sol";
|
|
19
20
|
|
|
20
21
|
// contracts
|
|
21
22
|
import {Diamond} from "@towns-protocol/diamond/src/Diamond.sol";
|
|
22
23
|
import {MultiInit} from "@towns-protocol/diamond/src/initializers/MultiInit.sol";
|
|
23
24
|
import {DiamondHelper} from "@towns-protocol/diamond/scripts/common/helpers/DiamondHelper.s.sol";
|
|
25
|
+
import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol";
|
|
24
26
|
|
|
25
27
|
// deployers
|
|
26
28
|
import {DeployFacet} from "../../common/DeployFacet.s.sol";
|
|
@@ -31,9 +33,11 @@ contract DeployAppRegistry is IDiamondInitHelper, DiamondHelper, Deployer {
|
|
|
31
33
|
|
|
32
34
|
DeployFacet private facetHelper = new DeployFacet();
|
|
33
35
|
DeploySpaceFactory private deploySpaceFactory = new DeploySpaceFactory();
|
|
36
|
+
DeploySimpleAppBeacon private deploySimpleAppBeacon = new DeploySimpleAppBeacon();
|
|
34
37
|
|
|
35
38
|
string internal constant APP_REGISTRY_SCHEMA = "address app, address client";
|
|
36
39
|
address internal spaceFactory;
|
|
40
|
+
address internal simpleAppBeacon;
|
|
37
41
|
|
|
38
42
|
function versionName() public pure override returns (string memory) {
|
|
39
43
|
return "appRegistry";
|
|
@@ -41,6 +45,7 @@ contract DeployAppRegistry is IDiamondInitHelper, DiamondHelper, Deployer {
|
|
|
41
45
|
|
|
42
46
|
function addImmutableCuts(address deployer) internal {
|
|
43
47
|
spaceFactory = deploySpaceFactory.deploy(deployer);
|
|
48
|
+
simpleAppBeacon = deploySimpleAppBeacon.deploy(deployer);
|
|
44
49
|
|
|
45
50
|
// Queue up all core facets for batch deployment
|
|
46
51
|
facetHelper.add("DiamondCutFacet");
|
|
@@ -81,7 +86,7 @@ contract DeployAppRegistry is IDiamondInitHelper, DiamondHelper, Deployer {
|
|
|
81
86
|
DeployOwnable.makeInitData(deployer)
|
|
82
87
|
);
|
|
83
88
|
|
|
84
|
-
facet = facetHelper.
|
|
89
|
+
facet = facetHelper.predictAddress("MetadataFacet");
|
|
85
90
|
addFacet(
|
|
86
91
|
makeCut(facet, FacetCutAction.Add, DeployMetadata.selectors()),
|
|
87
92
|
facet,
|
|
@@ -96,20 +101,10 @@ contract DeployAppRegistry is IDiamondInitHelper, DiamondHelper, Deployer {
|
|
|
96
101
|
facetHelper.add("AppRegistryFacet");
|
|
97
102
|
facetHelper.add("AppInstallerFacet");
|
|
98
103
|
facetHelper.add("AppFactoryFacet");
|
|
99
|
-
facetHelper.add("SimpleApp");
|
|
100
104
|
|
|
101
105
|
facetHelper.deployBatch(deployer);
|
|
102
106
|
|
|
103
|
-
address
|
|
104
|
-
address facet = facetHelper.getDeployedAddress("UpgradeableBeaconFacet");
|
|
105
|
-
|
|
106
|
-
addFacet(
|
|
107
|
-
makeCut(facet, FacetCutAction.Add, DeployUpgradeableBeacon.selectors()),
|
|
108
|
-
facet,
|
|
109
|
-
DeployUpgradeableBeacon.makeInitData(simpleApp)
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
facet = facetHelper.getDeployedAddress("AppRegistryFacet");
|
|
107
|
+
address facet = facetHelper.getDeployedAddress("AppRegistryFacet");
|
|
113
108
|
addFacet(
|
|
114
109
|
makeCut(facet, FacetCutAction.Add, DeployAppRegistryFacet.selectors()),
|
|
115
110
|
facet,
|
|
@@ -123,11 +118,17 @@ contract DeployAppRegistry is IDiamondInitHelper, DiamondHelper, Deployer {
|
|
|
123
118
|
DeployAppInstallerFacet.makeInitData()
|
|
124
119
|
);
|
|
125
120
|
|
|
121
|
+
IAppFactoryBase.Beacon[] memory beacons = new IAppFactoryBase.Beacon[](1);
|
|
122
|
+
beacons[0] = IAppFactoryBase.Beacon({
|
|
123
|
+
beaconId: deploySimpleAppBeacon.SIMPLE_APP_BEACON_ID(),
|
|
124
|
+
beacon: simpleAppBeacon
|
|
125
|
+
});
|
|
126
|
+
|
|
126
127
|
facet = facetHelper.getDeployedAddress("AppFactoryFacet");
|
|
127
128
|
addFacet(
|
|
128
129
|
makeCut(facet, FacetCutAction.Add, DeployAppFactoryFacet.selectors()),
|
|
129
130
|
facet,
|
|
130
|
-
DeployAppFactoryFacet.makeInitData()
|
|
131
|
+
DeployAppFactoryFacet.makeInitData(beacons, _getEntryPoint())
|
|
131
132
|
);
|
|
132
133
|
|
|
133
134
|
address multiInit = facetHelper.getDeployedAddress("MultiInit");
|
|
@@ -175,9 +176,15 @@ contract DeployAppRegistry is IDiamondInitHelper, DiamondHelper, Deployer {
|
|
|
175
176
|
|
|
176
177
|
Diamond.InitParams memory initDiamondCut = diamondInitParams(deployer);
|
|
177
178
|
|
|
178
|
-
vm.
|
|
179
|
+
vm.startBroadcast(deployer);
|
|
179
180
|
Diamond diamond = new Diamond(initDiamondCut);
|
|
181
|
+
vm.stopBroadcast();
|
|
180
182
|
|
|
181
183
|
return address(diamond);
|
|
182
184
|
}
|
|
185
|
+
|
|
186
|
+
function _getEntryPoint() internal returns (address) {
|
|
187
|
+
if (isTesting()) return address(new EntryPoint());
|
|
188
|
+
return 0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108;
|
|
189
|
+
}
|
|
183
190
|
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
import {IDiamondInitHelper} from "./IDiamondInitHelper.sol";
|
|
6
|
+
|
|
7
|
+
// libraries
|
|
8
|
+
import {DeployDiamondCut} from "@towns-protocol/diamond/scripts/deployments/facets/DeployDiamondCut.sol";
|
|
9
|
+
import {DeployDiamondLoupe} from "@towns-protocol/diamond/scripts/deployments/facets/DeployDiamondLoupe.sol";
|
|
10
|
+
import {DeployIntrospection} from "@towns-protocol/diamond/scripts/deployments/facets/DeployIntrospection.sol";
|
|
11
|
+
import {DeployOwnable} from "@towns-protocol/diamond/scripts/deployments/facets/DeployOwnable.sol";
|
|
12
|
+
import {DeployMetadata} from "../facets/DeployMetadata.s.sol";
|
|
13
|
+
import {DeployUpgradeableBeacon} from "../facets/DeployUpgradeableBeacon.s.sol";
|
|
14
|
+
import {LibString} from "solady/utils/LibString.sol";
|
|
15
|
+
|
|
16
|
+
// contracts
|
|
17
|
+
import {Diamond} from "@towns-protocol/diamond/src/Diamond.sol";
|
|
18
|
+
import {MultiInit} from "@towns-protocol/diamond/src/initializers/MultiInit.sol";
|
|
19
|
+
import {DiamondHelper} from "@towns-protocol/diamond/scripts/common/helpers/DiamondHelper.s.sol";
|
|
20
|
+
|
|
21
|
+
// deployers
|
|
22
|
+
import {DeployFacet} from "../../common/DeployFacet.s.sol";
|
|
23
|
+
import {Deployer} from "../../common/Deployer.s.sol";
|
|
24
|
+
|
|
25
|
+
contract DeploySimpleAppBeacon is DiamondHelper, Deployer, IDiamondInitHelper {
|
|
26
|
+
using LibString for string;
|
|
27
|
+
|
|
28
|
+
DeployFacet private facetHelper = new DeployFacet();
|
|
29
|
+
|
|
30
|
+
// keccak256("SimpleAppBeacon")
|
|
31
|
+
bytes32 public constant SIMPLE_APP_BEACON_ID =
|
|
32
|
+
0xff51c4406dd10a0ec471147fd1e468ff84c7fe0c8a9bc8165c6ac339490f6027;
|
|
33
|
+
|
|
34
|
+
function versionName() public pure override returns (string memory) {
|
|
35
|
+
return "simpleAppBeacon";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function diamondInitHelper(
|
|
39
|
+
address deployer,
|
|
40
|
+
string[] memory facetNames
|
|
41
|
+
) external override returns (FacetCut[] memory) {
|
|
42
|
+
// Queue up all requested facets for batch deployment
|
|
43
|
+
for (uint256 i; i < facetNames.length; ++i) {
|
|
44
|
+
facetHelper.add(facetNames[i]);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Deploy all requested facets in a single batch transaction
|
|
48
|
+
facetHelper.deployBatch(deployer);
|
|
49
|
+
|
|
50
|
+
for (uint256 i; i < facetNames.length; ++i) {
|
|
51
|
+
string memory facetName = facetNames[i];
|
|
52
|
+
address facet = facetHelper.getDeployedAddress(facetName);
|
|
53
|
+
|
|
54
|
+
if (facetName.eq("UpgradeableBeaconFacet")) {
|
|
55
|
+
addCut(makeCut(facet, FacetCutAction.Add, DeployUpgradeableBeacon.selectors()));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return baseFacets();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function diamondInitParams(address deployer) public returns (Diamond.InitParams memory) {
|
|
63
|
+
// Queue up feature facets for batch deployment
|
|
64
|
+
facetHelper.add("MultiInit");
|
|
65
|
+
facetHelper.add("UpgradeableBeaconFacet");
|
|
66
|
+
facetHelper.add("SimpleAppFacet");
|
|
67
|
+
|
|
68
|
+
// Deploy all facets in a batch
|
|
69
|
+
facetHelper.deployBatch(deployer);
|
|
70
|
+
|
|
71
|
+
// Add feature facets
|
|
72
|
+
address simpleApp = facetHelper.getDeployedAddress("SimpleAppFacet");
|
|
73
|
+
address facet = facetHelper.getDeployedAddress("UpgradeableBeaconFacet");
|
|
74
|
+
addFacet(
|
|
75
|
+
makeCut(facet, FacetCutAction.Add, DeployUpgradeableBeacon.selectors()),
|
|
76
|
+
facet,
|
|
77
|
+
DeployUpgradeableBeacon.makeInitData(simpleApp)
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
address multiInit = facetHelper.getDeployedAddress("MultiInit");
|
|
81
|
+
|
|
82
|
+
return
|
|
83
|
+
Diamond.InitParams({
|
|
84
|
+
baseFacets: baseFacets(),
|
|
85
|
+
init: multiInit,
|
|
86
|
+
initData: abi.encodeCall(MultiInit.multiInit, (_initAddresses, _initDatas))
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
|
|
91
|
+
/* Internal */
|
|
92
|
+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
93
|
+
|
|
94
|
+
function _coreFacets(address deployer) private {
|
|
95
|
+
// Queue up all core facets for batch deployment
|
|
96
|
+
facetHelper.add("DiamondCutFacet");
|
|
97
|
+
facetHelper.add("DiamondLoupeFacet");
|
|
98
|
+
facetHelper.add("IntrospectionFacet");
|
|
99
|
+
facetHelper.add("OwnableFacet");
|
|
100
|
+
facetHelper.add("MetadataFacet");
|
|
101
|
+
|
|
102
|
+
// Get predicted addresses
|
|
103
|
+
address facet = facetHelper.predictAddress("DiamondCutFacet");
|
|
104
|
+
addFacet(
|
|
105
|
+
makeCut(facet, FacetCutAction.Add, DeployDiamondCut.selectors()),
|
|
106
|
+
facet,
|
|
107
|
+
DeployDiamondCut.makeInitData()
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
facet = facetHelper.predictAddress("DiamondLoupeFacet");
|
|
111
|
+
addFacet(
|
|
112
|
+
makeCut(facet, FacetCutAction.Add, DeployDiamondLoupe.selectors()),
|
|
113
|
+
facet,
|
|
114
|
+
DeployDiamondLoupe.makeInitData()
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
facet = facetHelper.predictAddress("IntrospectionFacet");
|
|
118
|
+
addFacet(
|
|
119
|
+
makeCut(facet, FacetCutAction.Add, DeployIntrospection.selectors()),
|
|
120
|
+
facet,
|
|
121
|
+
DeployIntrospection.makeInitData()
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
facet = facetHelper.predictAddress("MetadataFacet");
|
|
125
|
+
addFacet(
|
|
126
|
+
makeCut(facet, FacetCutAction.Add, DeployMetadata.selectors()),
|
|
127
|
+
facet,
|
|
128
|
+
DeployMetadata.makeInitData(SIMPLE_APP_BEACON_ID, "")
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
facet = facetHelper.predictAddress("OwnableFacet");
|
|
132
|
+
addFacet(
|
|
133
|
+
makeCut(facet, FacetCutAction.Add, DeployOwnable.selectors()),
|
|
134
|
+
facet,
|
|
135
|
+
DeployOwnable.makeInitData(deployer)
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function __deploy(address deployer) internal override returns (address) {
|
|
140
|
+
_coreFacets(deployer);
|
|
141
|
+
|
|
142
|
+
Diamond.InitParams memory initDiamondCut = diamondInitParams(deployer);
|
|
143
|
+
|
|
144
|
+
vm.broadcast(deployer);
|
|
145
|
+
Diamond diamond = new Diamond(initDiamondCut);
|
|
146
|
+
|
|
147
|
+
return address(diamond);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -12,7 +12,6 @@ import {DeployIntrospection} from "@towns-protocol/diamond/scripts/deployments/f
|
|
|
12
12
|
import {DeployOwnable} from "@towns-protocol/diamond/scripts/deployments/facets/DeployOwnable.sol";
|
|
13
13
|
import {DeployPausable} from "@towns-protocol/diamond/scripts/deployments/facets/DeployPausable.sol";
|
|
14
14
|
import {DeployProxyManager} from "@towns-protocol/diamond/scripts/deployments/utils/DeployProxyManager.sol";
|
|
15
|
-
import {LibDeploy} from "@towns-protocol/diamond/src/utils/LibDeploy.sol";
|
|
16
15
|
import {DeployFeatureManager} from "../facets/DeployFeatureManager.s.sol";
|
|
17
16
|
import {DeployMetadata} from "../facets/DeployMetadata.s.sol";
|
|
18
17
|
import {DeployPricingModules} from "../facets/DeployPricingModules.s.sol";
|
|
@@ -10,13 +10,21 @@ import {IDiamond} from "@towns-protocol/diamond/src/IDiamond.sol";
|
|
|
10
10
|
import {LibDeploy} from "@towns-protocol/diamond/src/utils/LibDeploy.sol";
|
|
11
11
|
import {AppFactoryFacet} from "src/apps/facets/factory/AppFactoryFacet.sol";
|
|
12
12
|
import {DynamicArrayLib} from "solady/utils/DynamicArrayLib.sol";
|
|
13
|
+
import {IAppFactoryBase} from "src/apps/facets/factory/IAppFactory.sol";
|
|
13
14
|
|
|
14
15
|
library DeployAppFactoryFacet {
|
|
15
16
|
using DynamicArrayLib for DynamicArrayLib.DynamicArray;
|
|
16
17
|
|
|
17
18
|
function selectors() internal pure returns (bytes4[] memory res) {
|
|
18
|
-
DynamicArrayLib.DynamicArray memory arr = DynamicArrayLib.p().reserve(
|
|
19
|
+
DynamicArrayLib.DynamicArray memory arr = DynamicArrayLib.p().reserve(8);
|
|
20
|
+
arr.p(AppFactoryFacet.addBeacons.selector);
|
|
21
|
+
arr.p(AppFactoryFacet.removeBeacons.selector);
|
|
22
|
+
arr.p(AppFactoryFacet.getBeacon.selector);
|
|
23
|
+
arr.p(AppFactoryFacet.getBeacons.selector);
|
|
24
|
+
arr.p(AppFactoryFacet.setEntryPoint.selector);
|
|
25
|
+
arr.p(AppFactoryFacet.getEntryPoint.selector);
|
|
19
26
|
arr.p(AppFactoryFacet.createApp.selector);
|
|
27
|
+
arr.p(AppFactoryFacet.createAppByBeacon.selector);
|
|
20
28
|
bytes32[] memory selectors_ = arr.asBytes32Array();
|
|
21
29
|
assembly ("memory-safe") {
|
|
22
30
|
res := selectors_
|
|
@@ -35,8 +43,11 @@ library DeployAppFactoryFacet {
|
|
|
35
43
|
});
|
|
36
44
|
}
|
|
37
45
|
|
|
38
|
-
function makeInitData(
|
|
39
|
-
|
|
46
|
+
function makeInitData(
|
|
47
|
+
IAppFactoryBase.Beacon[] memory beacons,
|
|
48
|
+
address entryPoint
|
|
49
|
+
) internal pure returns (bytes memory) {
|
|
50
|
+
return abi.encodeCall(AppFactoryFacet.__AppFactory_init, (beacons, entryPoint));
|
|
40
51
|
}
|
|
41
52
|
|
|
42
53
|
function deploy() internal returns (address) {
|
|
@@ -6,7 +6,6 @@ import {IAppFactory} from "src/apps/facets/factory/IAppFactory.sol";
|
|
|
6
6
|
|
|
7
7
|
//contracts
|
|
8
8
|
import {Interaction} from "../common/Interaction.s.sol";
|
|
9
|
-
import {SimpleApp} from "src/apps/helpers/SimpleApp.sol";
|
|
10
9
|
import {IAppFactoryBase} from "src/apps/facets/factory/IAppFactory.sol";
|
|
11
10
|
|
|
12
11
|
contract InteractRegisterApp is Interaction, IAppFactoryBase {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
import {IAppFactory, IAppFactoryBase} from "src/apps/facets/factory/IAppFactory.sol";
|
|
6
|
+
|
|
7
|
+
// libraries
|
|
8
|
+
import {console} from "forge-std/console.sol";
|
|
9
|
+
|
|
10
|
+
// contracts
|
|
11
|
+
import {Interaction} from "../../common/Interaction.s.sol";
|
|
12
|
+
import {AlphaHelper} from "../helpers/AlphaHelper.sol";
|
|
13
|
+
import {DeployAppRegistry} from "../../deployments/diamonds/DeployAppRegistry.s.sol";
|
|
14
|
+
import {DeploySimpleAppBeacon} from "../../deployments/diamonds/DeploySimpleAppBeacon.s.sol";
|
|
15
|
+
|
|
16
|
+
// facet deployers
|
|
17
|
+
import {DeployAppRegistryFacet} from "../../deployments/facets/DeployAppRegistryFacet.s.sol";
|
|
18
|
+
import {DeployAppInstallerFacet} from "../../deployments/facets/DeployAppInstallerFacet.s.sol";
|
|
19
|
+
import {DeployAppFactoryFacet} from "../../deployments/facets/DeployAppFactoryFacet.s.sol";
|
|
20
|
+
|
|
21
|
+
contract InteractAppRegistry is Interaction, AlphaHelper {
|
|
22
|
+
DeployAppRegistry private deployHelper = new DeployAppRegistry();
|
|
23
|
+
DeploySimpleAppBeacon private beaconHelper = new DeploySimpleAppBeacon();
|
|
24
|
+
|
|
25
|
+
function __interact(address deployer) internal override {
|
|
26
|
+
// Get the deployed AppRegistry diamond address
|
|
27
|
+
address appRegistry = getDeployment("appRegistry");
|
|
28
|
+
address spaceFactory = getDeployment("spaceFactory");
|
|
29
|
+
address simpleAppBeacon = getDeployment("simpleAppBeacon");
|
|
30
|
+
address entryPoint = getDeployment("entryPoint");
|
|
31
|
+
|
|
32
|
+
console.log("AppRegistry Diamond:", appRegistry);
|
|
33
|
+
console.log("Space Factory:", spaceFactory);
|
|
34
|
+
console.log("Simple App Beacon:", simpleAppBeacon);
|
|
35
|
+
|
|
36
|
+
// Deploy new facet implementations
|
|
37
|
+
console.log("\n=== Deploying New Facets ===");
|
|
38
|
+
vm.setEnv("OVERRIDE_DEPLOYMENTS", "1");
|
|
39
|
+
|
|
40
|
+
address appRegistryFacet = DeployAppRegistryFacet.deploy();
|
|
41
|
+
console.log("AppRegistryFacet deployed at:", appRegistryFacet);
|
|
42
|
+
|
|
43
|
+
address appInstallerFacet = DeployAppInstallerFacet.deploy();
|
|
44
|
+
console.log("AppInstallerFacet deployed at:", appInstallerFacet);
|
|
45
|
+
|
|
46
|
+
address appFactoryFacet = DeployAppFactoryFacet.deploy();
|
|
47
|
+
console.log("AppFactoryFacet deployed at:", appFactoryFacet);
|
|
48
|
+
|
|
49
|
+
// Add the cuts for the new facet implementations
|
|
50
|
+
addCut(DeployAppRegistryFacet.makeCut(appRegistryFacet, FacetCutAction.Replace));
|
|
51
|
+
addCut(DeployAppInstallerFacet.makeCut(appInstallerFacet, FacetCutAction.Replace));
|
|
52
|
+
addCut(DeployAppFactoryFacet.makeCut(appFactoryFacet, FacetCutAction.Replace));
|
|
53
|
+
|
|
54
|
+
// Prepare initialization data for AppFactoryFacet with the beacon configuration
|
|
55
|
+
IAppFactoryBase.Beacon[] memory beacons = new IAppFactoryBase.Beacon[](1);
|
|
56
|
+
beacons[0] = IAppFactoryBase.Beacon({
|
|
57
|
+
beaconId: beaconHelper.SIMPLE_APP_BEACON_ID(),
|
|
58
|
+
beacon: simpleAppBeacon
|
|
59
|
+
});
|
|
60
|
+
bytes memory initData = DeployAppFactoryFacet.makeInitData(beacons, entryPoint);
|
|
61
|
+
|
|
62
|
+
// Generate and execute smart cuts with initialization
|
|
63
|
+
console.log("\n=== Executing Diamond Cut with Initialization ===");
|
|
64
|
+
executeDiamondCutsWithLogging(
|
|
65
|
+
deployer,
|
|
66
|
+
appRegistry,
|
|
67
|
+
"AppRegistry",
|
|
68
|
+
deployHelper,
|
|
69
|
+
appFactoryFacet,
|
|
70
|
+
initData
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
console.log("\n=== Diamond Cut Complete ===");
|
|
74
|
+
}
|
|
75
|
+
}
|
package/src/apps/BaseApp.sol
CHANGED
|
@@ -12,18 +12,21 @@ import {ITownsApp} from "./ITownsApp.sol";
|
|
|
12
12
|
/// @dev Inheriting contracts should override _onInstall and _onUninstall as needed
|
|
13
13
|
/// @dev Implements IModule, IExecutionModule, and ITownsApp interfaces
|
|
14
14
|
abstract contract BaseApp is ITownsApp {
|
|
15
|
-
receive() external payable {
|
|
15
|
+
receive() external payable virtual {
|
|
16
16
|
_onPayment(msg.sender, msg.value);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
|
|
19
|
+
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
|
|
21
20
|
return
|
|
21
|
+
interfaceId == type(ITownsApp).interfaceId ||
|
|
22
22
|
interfaceId == type(IExecutionModule).interfaceId ||
|
|
23
|
-
interfaceId == type(IModule).interfaceId
|
|
24
|
-
interfaceId == type(ITownsApp).interfaceId;
|
|
23
|
+
interfaceId == type(IModule).interfaceId;
|
|
25
24
|
}
|
|
26
25
|
|
|
26
|
+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
|
|
27
|
+
/* Base App Functions */
|
|
28
|
+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
29
|
+
|
|
27
30
|
/// @notice Required by IModule - called when module is installed
|
|
28
31
|
function onInstall(bytes calldata postInstallData) external {
|
|
29
32
|
_onInstall(postInstallData);
|
|
@@ -46,7 +49,7 @@ abstract contract BaseApp is ITownsApp {
|
|
|
46
49
|
return _accessDuration();
|
|
47
50
|
}
|
|
48
51
|
|
|
49
|
-
//
|
|
52
|
+
// Hooks
|
|
50
53
|
function _onInstall(bytes calldata postInstallData) internal virtual {}
|
|
51
54
|
|
|
52
55
|
function _onUninstall(bytes calldata postUninstallData) internal virtual {}
|
package/src/apps/ITownsApp.sol
CHANGED
|
@@ -10,6 +10,10 @@ import {IModule} from "@erc6900/reference-implementation/interfaces/IModule.sol"
|
|
|
10
10
|
/// @dev Combines IModule (module lifecycle), and IExecutionModule (execution)
|
|
11
11
|
/// @dev Apps must implement required permissions and support these interfaces
|
|
12
12
|
interface ITownsApp is IModule, IExecutionModule {
|
|
13
|
+
/// @notice Initializes the app
|
|
14
|
+
/// @param data The data to initialize the app
|
|
15
|
+
function initialize(bytes calldata data) external;
|
|
16
|
+
|
|
13
17
|
/// @notice Returns the required permissions for the app
|
|
14
18
|
/// @return permissions The required permissions for the app
|
|
15
19
|
function requiredPermissions() external view returns (bytes32[] memory);
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.29;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
import {IAppFactoryBase} from "./IAppFactory.sol";
|
|
6
|
+
import {ITownsApp} from "../../ITownsApp.sol";
|
|
7
|
+
|
|
8
|
+
// libraries
|
|
9
|
+
import {LibClone} from "solady/utils/LibClone.sol";
|
|
10
|
+
import {CustomRevert} from "../../../utils/libraries/CustomRevert.sol";
|
|
11
|
+
import {AppFactoryStorage} from "./AppFactoryStorage.sol";
|
|
12
|
+
import {EnumerableSetLib} from "solady/utils/EnumerableSetLib.sol";
|
|
13
|
+
import {LibAppRegistry} from "../registry/LibAppRegistry.sol";
|
|
14
|
+
|
|
15
|
+
// contracts
|
|
16
|
+
import {Facet} from "@towns-protocol/diamond/src/facets/Facet.sol";
|
|
17
|
+
|
|
18
|
+
/// @title AppInstallerFacet
|
|
19
|
+
/// @author Towns Protocol
|
|
20
|
+
/// @notice Facet for installing apps to spaces
|
|
21
|
+
abstract contract AppFactoryBase is IAppFactoryBase {
|
|
22
|
+
using CustomRevert for bytes4;
|
|
23
|
+
using EnumerableSetLib for EnumerableSetLib.Bytes32Set;
|
|
24
|
+
|
|
25
|
+
function _addBeacons(Beacon[] calldata beacons) internal {
|
|
26
|
+
AppFactoryStorage.Layout storage $ = AppFactoryStorage.getLayout();
|
|
27
|
+
uint256 length = beacons.length;
|
|
28
|
+
for (uint256 i; i < length; ++i) {
|
|
29
|
+
Beacon calldata beacon = beacons[i];
|
|
30
|
+
if (beacon.beacon == address(0)) AppFactory__InvalidAddressInput.selector.revertWith();
|
|
31
|
+
if (beacon.beaconId == bytes32(0)) AppFactory__InvalidBeaconId.selector.revertWith();
|
|
32
|
+
if ($.beaconIds.contains(beacon.beaconId))
|
|
33
|
+
AppFactory__BeaconAlreadyExists.selector.revertWith();
|
|
34
|
+
$.beacons[beacon.beaconId] = beacon.beacon;
|
|
35
|
+
$.beaconIds.add(beacon.beaconId);
|
|
36
|
+
emit BeaconAdded(beacon.beaconId, beacon.beacon);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function _removeBeacons(bytes32[] calldata beaconIds) internal {
|
|
41
|
+
AppFactoryStorage.Layout storage $ = AppFactoryStorage.getLayout();
|
|
42
|
+
uint256 length = beaconIds.length;
|
|
43
|
+
for (uint256 i; i < length; ++i) {
|
|
44
|
+
bytes32 beaconId = beaconIds[i];
|
|
45
|
+
address beacon = $.beacons[beaconId];
|
|
46
|
+
|
|
47
|
+
if (beaconId == bytes32(0)) AppFactory__InvalidBeaconId.selector.revertWith();
|
|
48
|
+
if (beacon == address(0)) AppFactory__BeaconNotFound.selector.revertWith();
|
|
49
|
+
|
|
50
|
+
delete $.beacons[beaconId];
|
|
51
|
+
$.beaconIds.remove(beaconId);
|
|
52
|
+
emit BeaconRemoved(beaconId, beacon);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function _setEntryPoint(address entryPoint) internal {
|
|
57
|
+
AppFactoryStorage.Layout storage $ = AppFactoryStorage.getLayout();
|
|
58
|
+
address oldEntryPoint = $.entryPoint;
|
|
59
|
+
$.entryPoint = entryPoint;
|
|
60
|
+
emit EntryPointSet(oldEntryPoint, entryPoint);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function _getBeacon(bytes32 beaconId) internal view returns (address beacon) {
|
|
64
|
+
return AppFactoryStorage.getLayout().beacons[beaconId];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function _getBeacons() internal view returns (bytes32[] memory beaconIds) {
|
|
68
|
+
return AppFactoryStorage.getLayout().beaconIds.values();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function _getDefaultBeaconId() internal view returns (bytes32 beaconId) {
|
|
72
|
+
return AppFactoryStorage.getLayout().beaconIds.at(0);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// @notice Create an upgradeable simple app contract
|
|
76
|
+
/// @param params The parameters of the app
|
|
77
|
+
function _createApp(
|
|
78
|
+
bytes32 beaconId,
|
|
79
|
+
AppParams calldata params
|
|
80
|
+
) internal returns (address app) {
|
|
81
|
+
AppFactoryStorage.Layout storage $ = AppFactoryStorage.getLayout();
|
|
82
|
+
|
|
83
|
+
address beacon = $.beacons[beaconId];
|
|
84
|
+
if (beacon == address(0)) AppFactory__BeaconNotFound.selector.revertWith();
|
|
85
|
+
|
|
86
|
+
uint48 accessDuration = LibAppRegistry.validateDuration(params.accessDuration);
|
|
87
|
+
|
|
88
|
+
app = LibClone.deployERC1967BeaconProxy(beacon);
|
|
89
|
+
ITownsApp(app).initialize(
|
|
90
|
+
abi.encode(
|
|
91
|
+
msg.sender,
|
|
92
|
+
params.name,
|
|
93
|
+
params.permissions,
|
|
94
|
+
params.installPrice,
|
|
95
|
+
accessDuration,
|
|
96
|
+
params.client,
|
|
97
|
+
$.entryPoint,
|
|
98
|
+
address(this)
|
|
99
|
+
)
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function _validateParams(AppParams calldata params) internal pure {
|
|
104
|
+
if (bytes(params.name).length == 0) AppFactory__InvalidAppName.selector.revertWith();
|
|
105
|
+
if (params.permissions.length == 0) AppFactory__InvalidArrayInput.selector.revertWith();
|
|
106
|
+
if (params.client == address(0)) AppFactory__InvalidAddressInput.selector.revertWith();
|
|
107
|
+
}
|
|
108
|
+
}
|