@towns-protocol/contracts 0.0.375 → 0.0.377
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 +18 -15
- package/scripts/deployments/facets/DeployAppInstallerFacet.s.sol +48 -0
- package/scripts/deployments/facets/DeployAppRegistryFacet.s.sol +1 -5
- package/src/apps/facets/installer/AppInstallerFacet.sol +66 -0
- package/src/apps/facets/installer/IAppInstaller.sol +35 -0
- package/src/apps/facets/registry/AppRegistryBase.sol +5 -4
- package/src/apps/facets/registry/AppRegistryFacet.sol +3 -47
- package/src/apps/facets/registry/IAppRegistry.sol +0 -23
- package/src/spaces/facets/Entitled.sol +3 -3
- package/src/spaces/facets/account/AppAccountBase.sol +21 -1
- package/src/spaces/facets/account/AppAccountStorage.sol +0 -23
- package/src/spaces/facets/tipping/ITipping.sol +1 -1
- package/src/spaces/facets/tipping/TippingBase.sol +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@towns-protocol/contracts",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.377",
|
|
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.377",
|
|
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": "a289c507ab3ae080d0b07e9f881743223580fdf4"
|
|
61
61
|
}
|
|
@@ -13,6 +13,8 @@ import {LibString} from "solady/utils/LibString.sol";
|
|
|
13
13
|
import {DeployMetadata} from "../facets/DeployMetadata.s.sol";
|
|
14
14
|
import {DeployAppRegistryFacet} from "../facets/DeployAppRegistryFacet.s.sol";
|
|
15
15
|
import {DeployUpgradeableBeacon} from "../facets/DeployUpgradeableBeacon.s.sol";
|
|
16
|
+
import {DeployAppInstallerFacet} from "../facets/DeployAppInstallerFacet.s.sol";
|
|
17
|
+
import {DeploySpaceFactory} from "../diamonds/DeploySpaceFactory.s.sol";
|
|
16
18
|
|
|
17
19
|
// contracts
|
|
18
20
|
import {Diamond} from "@towns-protocol/diamond/src/Diamond.sol";
|
|
@@ -26,29 +28,19 @@ import {Deployer} from "../../common/Deployer.s.sol";
|
|
|
26
28
|
contract DeployAppRegistry is IDiamondInitHelper, DiamondHelper, Deployer {
|
|
27
29
|
using LibString for string;
|
|
28
30
|
|
|
29
|
-
address private SPACE_FACTORY;
|
|
30
|
-
|
|
31
31
|
DeployFacet private facetHelper = new DeployFacet();
|
|
32
|
+
DeploySpaceFactory private deploySpaceFactory = new DeploySpaceFactory();
|
|
32
33
|
|
|
33
34
|
string internal constant APP_REGISTRY_SCHEMA = "address app, address client";
|
|
35
|
+
address internal spaceFactory;
|
|
34
36
|
|
|
35
37
|
function versionName() public pure override returns (string memory) {
|
|
36
38
|
return "appRegistry";
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
function setSpaceFactory(address factory) public {
|
|
40
|
-
SPACE_FACTORY = factory;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function getSpaceFactory() public returns (address) {
|
|
44
|
-
if (SPACE_FACTORY != address(0)) {
|
|
45
|
-
return SPACE_FACTORY;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return getDeployment("spaceFactory");
|
|
49
|
-
}
|
|
50
|
-
|
|
51
41
|
function addImmutableCuts(address deployer) internal {
|
|
42
|
+
spaceFactory = deploySpaceFactory.deploy(deployer);
|
|
43
|
+
|
|
52
44
|
// Queue up all core facets for batch deployment
|
|
53
45
|
facetHelper.add("DiamondCutFacet");
|
|
54
46
|
facetHelper.add("DiamondLoupeFacet");
|
|
@@ -94,6 +86,7 @@ contract DeployAppRegistry is IDiamondInitHelper, DiamondHelper, Deployer {
|
|
|
94
86
|
facetHelper.add("MetadataFacet");
|
|
95
87
|
facetHelper.add("UpgradeableBeaconFacet");
|
|
96
88
|
facetHelper.add("AppRegistryFacet");
|
|
89
|
+
facetHelper.add("AppInstallerFacet");
|
|
97
90
|
facetHelper.add("SimpleApp");
|
|
98
91
|
|
|
99
92
|
facetHelper.deployBatch(deployer);
|
|
@@ -118,7 +111,14 @@ contract DeployAppRegistry is IDiamondInitHelper, DiamondHelper, Deployer {
|
|
|
118
111
|
addFacet(
|
|
119
112
|
makeCut(facet, FacetCutAction.Add, DeployAppRegistryFacet.selectors()),
|
|
120
113
|
facet,
|
|
121
|
-
DeployAppRegistryFacet.makeInitData(
|
|
114
|
+
DeployAppRegistryFacet.makeInitData(spaceFactory, APP_REGISTRY_SCHEMA, address(0))
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
facet = facetHelper.getDeployedAddress("AppInstallerFacet");
|
|
118
|
+
addFacet(
|
|
119
|
+
makeCut(facet, FacetCutAction.Add, DeployAppInstallerFacet.selectors()),
|
|
120
|
+
facet,
|
|
121
|
+
DeployAppInstallerFacet.makeInitData()
|
|
122
122
|
);
|
|
123
123
|
|
|
124
124
|
address multiInit = facetHelper.getDeployedAddress("MultiInit");
|
|
@@ -150,6 +150,9 @@ contract DeployAppRegistry is IDiamondInitHelper, DiamondHelper, Deployer {
|
|
|
150
150
|
if (facetName.eq("AppRegistryFacet")) {
|
|
151
151
|
addCut(makeCut(facet, FacetCutAction.Add, DeployAppRegistryFacet.selectors()));
|
|
152
152
|
}
|
|
153
|
+
if (facetName.eq("AppInstallerFacet")) {
|
|
154
|
+
addCut(makeCut(facet, FacetCutAction.Add, DeployAppInstallerFacet.selectors()));
|
|
155
|
+
}
|
|
153
156
|
}
|
|
154
157
|
|
|
155
158
|
return baseFacets();
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
//interfaces
|
|
5
|
+
import {IDiamond} from "@towns-protocol/diamond/src/IDiamond.sol";
|
|
6
|
+
|
|
7
|
+
//libraries
|
|
8
|
+
|
|
9
|
+
//contracts
|
|
10
|
+
import {LibDeploy} from "@towns-protocol/diamond/src/utils/LibDeploy.sol";
|
|
11
|
+
import {AppInstallerFacet} from "src/apps/facets/installer/AppInstallerFacet.sol";
|
|
12
|
+
import {DynamicArrayLib} from "solady/utils/DynamicArrayLib.sol";
|
|
13
|
+
|
|
14
|
+
library DeployAppInstallerFacet {
|
|
15
|
+
using DynamicArrayLib for DynamicArrayLib.DynamicArray;
|
|
16
|
+
|
|
17
|
+
function selectors() internal pure returns (bytes4[] memory res) {
|
|
18
|
+
DynamicArrayLib.DynamicArray memory arr = DynamicArrayLib.p().reserve(4);
|
|
19
|
+
arr.p(AppInstallerFacet.installApp.selector);
|
|
20
|
+
arr.p(AppInstallerFacet.uninstallApp.selector);
|
|
21
|
+
arr.p(AppInstallerFacet.updateApp.selector);
|
|
22
|
+
arr.p(AppInstallerFacet.renewApp.selector);
|
|
23
|
+
bytes32[] memory selectors_ = arr.asBytes32Array();
|
|
24
|
+
assembly ("memory-safe") {
|
|
25
|
+
res := selectors_
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function makeCut(
|
|
30
|
+
address facetAddress,
|
|
31
|
+
IDiamond.FacetCutAction action
|
|
32
|
+
) internal pure returns (IDiamond.FacetCut memory) {
|
|
33
|
+
return
|
|
34
|
+
IDiamond.FacetCut({
|
|
35
|
+
action: action,
|
|
36
|
+
facetAddress: facetAddress,
|
|
37
|
+
functionSelectors: selectors()
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function makeInitData() internal pure returns (bytes memory) {
|
|
42
|
+
return abi.encodeCall(AppInstallerFacet.__AppInstaller_init, ());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function deploy() internal returns (address) {
|
|
46
|
+
return LibDeploy.deployCode("AppInstallerFacet.sol", "");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -16,7 +16,7 @@ library DeployAppRegistryFacet {
|
|
|
16
16
|
using DynamicArrayLib for DynamicArrayLib.DynamicArray;
|
|
17
17
|
|
|
18
18
|
function selectors() internal pure returns (bytes4[] memory res) {
|
|
19
|
-
DynamicArrayLib.DynamicArray memory arr = DynamicArrayLib.p().reserve(
|
|
19
|
+
DynamicArrayLib.DynamicArray memory arr = DynamicArrayLib.p().reserve(14);
|
|
20
20
|
arr.p(AppRegistryFacet.getAppSchema.selector);
|
|
21
21
|
arr.p(AppRegistryFacet.getAppSchemaId.selector);
|
|
22
22
|
arr.p(AppRegistryFacet.getAppById.selector);
|
|
@@ -25,16 +25,12 @@ library DeployAppRegistryFacet {
|
|
|
25
25
|
arr.p(AppRegistryFacet.removeApp.selector);
|
|
26
26
|
arr.p(AppRegistryFacet.createApp.selector);
|
|
27
27
|
arr.p(AppRegistryFacet.upgradeApp.selector);
|
|
28
|
-
arr.p(AppRegistryFacet.installApp.selector);
|
|
29
|
-
arr.p(AppRegistryFacet.uninstallApp.selector);
|
|
30
|
-
arr.p(AppRegistryFacet.updateApp.selector);
|
|
31
28
|
arr.p(AppRegistryFacet.getAppPrice.selector);
|
|
32
29
|
arr.p(AppRegistryFacet.getAppDuration.selector);
|
|
33
30
|
arr.p(AppRegistryFacet.adminRegisterAppSchema.selector);
|
|
34
31
|
arr.p(AppRegistryFacet.adminBanApp.selector);
|
|
35
32
|
arr.p(AppRegistryFacet.isAppBanned.selector);
|
|
36
33
|
arr.p(AppRegistryFacet.getAppByClient.selector);
|
|
37
|
-
arr.p(AppRegistryFacet.renewApp.selector);
|
|
38
34
|
bytes32[] memory selectors_ = arr.asBytes32Array();
|
|
39
35
|
assembly ("memory-safe") {
|
|
40
36
|
res := selectors_
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.29;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
import {ITownsApp} from "../../ITownsApp.sol";
|
|
6
|
+
import {IAppAccount} from "../../../spaces/facets/account/IAppAccount.sol";
|
|
7
|
+
import {IAppInstaller} from "./IAppInstaller.sol";
|
|
8
|
+
|
|
9
|
+
// libraries
|
|
10
|
+
|
|
11
|
+
// contracts
|
|
12
|
+
import {Facet} from "@towns-protocol/diamond/src/facets/Facet.sol";
|
|
13
|
+
import {AppRegistryBase} from "../registry/AppRegistryBase.sol";
|
|
14
|
+
import {ReentrancyGuardTransient} from "solady/utils/ReentrancyGuardTransient.sol";
|
|
15
|
+
|
|
16
|
+
/// @title AppInstallerFacet
|
|
17
|
+
/// @author Towns Protocol
|
|
18
|
+
/// @notice Facet for installing apps to spaces
|
|
19
|
+
contract AppInstallerFacet is IAppInstaller, AppRegistryBase, ReentrancyGuardTransient, Facet {
|
|
20
|
+
function __AppInstaller_init() external onlyInitializing {
|
|
21
|
+
_addInterface(type(IAppInstaller).interfaceId);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/// @notice Install an app
|
|
25
|
+
/// @param app The app address to install
|
|
26
|
+
/// @param space The space to install the app to
|
|
27
|
+
/// @param data The data to pass to the app's onInstall function
|
|
28
|
+
function installApp(
|
|
29
|
+
ITownsApp app,
|
|
30
|
+
IAppAccount space,
|
|
31
|
+
bytes calldata data
|
|
32
|
+
) external payable nonReentrant onlyAllowed(space) {
|
|
33
|
+
_installApp(address(app), address(space), data);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// @notice Uninstall an app
|
|
37
|
+
/// @param app The app address to uninstall
|
|
38
|
+
/// @param space The space to uninstall the app from
|
|
39
|
+
/// @param data The data to pass to the app's onUninstall function
|
|
40
|
+
function uninstallApp(
|
|
41
|
+
ITownsApp app,
|
|
42
|
+
IAppAccount space,
|
|
43
|
+
bytes calldata data
|
|
44
|
+
) external nonReentrant onlyAllowed(space) {
|
|
45
|
+
_uninstallApp(address(app), address(space), data);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// @notice Update an app to the latest version
|
|
49
|
+
/// @param app The app address to update
|
|
50
|
+
/// @param space The space to update the app to
|
|
51
|
+
function updateApp(ITownsApp app, IAppAccount space) external nonReentrant onlyAllowed(space) {
|
|
52
|
+
_updateApp(address(app), address(space));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// @notice Renew an app
|
|
56
|
+
/// @param app The app address to renew
|
|
57
|
+
/// @param space The space to renew the app for
|
|
58
|
+
/// @param data The data to pass to the app's onRenewApp function
|
|
59
|
+
function renewApp(
|
|
60
|
+
ITownsApp app,
|
|
61
|
+
IAppAccount space,
|
|
62
|
+
bytes calldata data
|
|
63
|
+
) external payable nonReentrant onlyAllowed(space) {
|
|
64
|
+
_renewApp(address(app), address(space), data);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.29;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
import {ITownsApp} from "../../ITownsApp.sol";
|
|
6
|
+
import {IAppAccount} from "../../../spaces/facets/account/IAppAccount.sol";
|
|
7
|
+
|
|
8
|
+
// libraries
|
|
9
|
+
|
|
10
|
+
// contracts
|
|
11
|
+
|
|
12
|
+
interface IAppInstaller {
|
|
13
|
+
/// @notice Install an app
|
|
14
|
+
/// @param app The app address to install
|
|
15
|
+
/// @param account The account to install the app to
|
|
16
|
+
/// @param data The data to pass to the app's onInstall function
|
|
17
|
+
function installApp(ITownsApp app, IAppAccount account, bytes calldata data) external payable;
|
|
18
|
+
|
|
19
|
+
/// @notice Uninstall an app
|
|
20
|
+
/// @param app The app address to uninstall
|
|
21
|
+
/// @param account The account to uninstall the app from
|
|
22
|
+
/// @param data The data to pass to the app's onUninstall function
|
|
23
|
+
function uninstallApp(ITownsApp app, IAppAccount account, bytes calldata data) external;
|
|
24
|
+
|
|
25
|
+
/// @notice Update an app to the latest version
|
|
26
|
+
/// @param app The app address to update
|
|
27
|
+
/// @param account The account to update the app to
|
|
28
|
+
function updateApp(ITownsApp app, IAppAccount account) external;
|
|
29
|
+
|
|
30
|
+
/// @notice Renew an app
|
|
31
|
+
/// @param app The app address to renew
|
|
32
|
+
/// @param account The account to renew the app for
|
|
33
|
+
/// @param data The data to pass to the app's onRenewApp function
|
|
34
|
+
function renewApp(ITownsApp app, IAppAccount account, bytes calldata data) external payable;
|
|
35
|
+
}
|
|
@@ -35,6 +35,11 @@ abstract contract AppRegistryBase is IAppRegistryBase, SchemaBase, AttestationBa
|
|
|
35
35
|
|
|
36
36
|
uint48 private constant MAX_DURATION = 365 days;
|
|
37
37
|
|
|
38
|
+
modifier onlyAllowed(IAppAccount account) {
|
|
39
|
+
if (IERC173(address(account)).owner() != msg.sender) NotAllowed.selector.revertWith();
|
|
40
|
+
_;
|
|
41
|
+
}
|
|
42
|
+
|
|
38
43
|
function __AppRegistry_init_unchained(
|
|
39
44
|
address spaceFactory,
|
|
40
45
|
string calldata schema,
|
|
@@ -321,10 +326,6 @@ abstract contract AppRegistryBase is IAppRegistryBase, SchemaBase, AttestationBa
|
|
|
321
326
|
emit AppRenewed(app, account, appId);
|
|
322
327
|
}
|
|
323
328
|
|
|
324
|
-
function _onlyAllowed(address account) internal view {
|
|
325
|
-
if (IERC173(account).owner() != msg.sender) NotAllowed.selector.revertWith();
|
|
326
|
-
}
|
|
327
|
-
|
|
328
329
|
function _getProtocolFee(uint256 installPrice) internal view returns (uint256) {
|
|
329
330
|
IPlatformRequirements platform = _getPlatformRequirements();
|
|
330
331
|
uint256 baseFee = platform.getMembershipFee();
|
|
@@ -16,6 +16,9 @@ import {Facet} from "@towns-protocol/diamond/src/facets/Facet.sol";
|
|
|
16
16
|
import {ReentrancyGuard} from "solady/utils/ReentrancyGuard.sol";
|
|
17
17
|
import {OwnableBase} from "@towns-protocol/diamond/src/facets/ownable/OwnableBase.sol";
|
|
18
18
|
|
|
19
|
+
/// @title AppRegistryFacet
|
|
20
|
+
/// @author Towns Protocol
|
|
21
|
+
/// @notice Facet for managing app registry
|
|
19
22
|
contract AppRegistryFacet is IAppRegistry, AppRegistryBase, OwnableBase, ReentrancyGuard, Facet {
|
|
20
23
|
function __AppRegistry_init(
|
|
21
24
|
address spaceFactory,
|
|
@@ -95,53 +98,6 @@ contract AppRegistryFacet is IAppRegistry, AppRegistryBase, OwnableBase, Reentra
|
|
|
95
98
|
/* Space Functions */
|
|
96
99
|
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
97
100
|
|
|
98
|
-
/// @notice Install an app
|
|
99
|
-
/// @param app The app address to install
|
|
100
|
-
/// @param space The space to install the app to
|
|
101
|
-
/// @param data The data to pass to the app's onInstall function
|
|
102
|
-
function installApp(
|
|
103
|
-
ITownsApp app,
|
|
104
|
-
IAppAccount space,
|
|
105
|
-
bytes calldata data
|
|
106
|
-
) external payable nonReentrant {
|
|
107
|
-
_onlyAllowed(address(space));
|
|
108
|
-
return _installApp(address(app), address(space), data);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/// @notice Uninstall an app
|
|
112
|
-
/// @param app The app address to uninstall
|
|
113
|
-
/// @param space The space to uninstall the app from
|
|
114
|
-
/// @param data The data to pass to the app's onUninstall function
|
|
115
|
-
function uninstallApp(
|
|
116
|
-
ITownsApp app,
|
|
117
|
-
IAppAccount space,
|
|
118
|
-
bytes calldata data
|
|
119
|
-
) external nonReentrant {
|
|
120
|
-
_onlyAllowed(address(space));
|
|
121
|
-
_uninstallApp(address(app), address(space), data);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/// @notice Update an app to the latest version
|
|
125
|
-
/// @param app The app address to update
|
|
126
|
-
/// @param space The space to update the app to
|
|
127
|
-
function updateApp(ITownsApp app, IAppAccount space) external nonReentrant {
|
|
128
|
-
_onlyAllowed(address(space));
|
|
129
|
-
_updateApp(address(app), address(space));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/// @notice Renew an app
|
|
133
|
-
/// @param app The app address to renew
|
|
134
|
-
/// @param account The account to renew the app for
|
|
135
|
-
/// @param data The data to pass to the app's onRenewApp function
|
|
136
|
-
function renewApp(
|
|
137
|
-
ITownsApp app,
|
|
138
|
-
IAppAccount account,
|
|
139
|
-
bytes calldata data
|
|
140
|
-
) external payable nonReentrant {
|
|
141
|
-
_onlyAllowed(address(account));
|
|
142
|
-
_renewApp(address(app), address(account), data);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
101
|
/// @notice Get the schema structure used for registering modules
|
|
146
102
|
/// @return The schema structure
|
|
147
103
|
function getAppSchema() external view returns (string memory) {
|
|
@@ -140,29 +140,6 @@ interface IAppRegistry is IAppRegistryBase {
|
|
|
140
140
|
/// @param appId The app ID to remove
|
|
141
141
|
function removeApp(bytes32 appId) external;
|
|
142
142
|
|
|
143
|
-
/// @notice Renew an app
|
|
144
|
-
/// @param app The app address to renew
|
|
145
|
-
/// @param account The account to renew the app for
|
|
146
|
-
/// @param data The data to pass to the app's onRenewApp function
|
|
147
|
-
function renewApp(ITownsApp app, IAppAccount account, bytes calldata data) external payable;
|
|
148
|
-
|
|
149
|
-
/// @notice Install an app
|
|
150
|
-
/// @param app The app address to install
|
|
151
|
-
/// @param account The account to install the app to
|
|
152
|
-
/// @param data The data to pass to the app's onInstall function
|
|
153
|
-
function installApp(ITownsApp app, IAppAccount account, bytes calldata data) external payable;
|
|
154
|
-
|
|
155
|
-
/// @notice Uninstall an app
|
|
156
|
-
/// @param app The app address to uninstall
|
|
157
|
-
/// @param account The account to uninstall the app from
|
|
158
|
-
/// @param data The data to pass to the app's onUninstall function
|
|
159
|
-
function uninstallApp(ITownsApp app, IAppAccount account, bytes calldata data) external;
|
|
160
|
-
|
|
161
|
-
/// @notice Update an app to the latest version
|
|
162
|
-
/// @param app The app address to update
|
|
163
|
-
/// @param account The account to update the app to
|
|
164
|
-
function updateApp(ITownsApp app, IAppAccount account) external;
|
|
165
|
-
|
|
166
143
|
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
|
|
167
144
|
/* Admin */
|
|
168
145
|
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
@@ -14,13 +14,13 @@ import {CustomRevert} from "../../utils/libraries/CustomRevert.sol";
|
|
|
14
14
|
import {EntitlementsManagerStorage} from "./entitlements/EntitlementsManagerStorage.sol";
|
|
15
15
|
import {MembershipStorage} from "./membership/MembershipStorage.sol";
|
|
16
16
|
import {BanningStorage} from "./banning/BanningStorage.sol";
|
|
17
|
-
import {
|
|
17
|
+
import {AppAccountBase} from "./account/AppAccountBase.sol";
|
|
18
18
|
import {DependencyLib} from "./DependencyLib.sol";
|
|
19
19
|
|
|
20
20
|
// contracts
|
|
21
21
|
import {TokenOwnableBase} from "@towns-protocol/diamond/src/facets/ownable/token/TokenOwnableBase.sol";
|
|
22
22
|
|
|
23
|
-
abstract contract Entitled is IEntitlementBase, TokenOwnableBase {
|
|
23
|
+
abstract contract Entitled is IEntitlementBase, TokenOwnableBase, AppAccountBase {
|
|
24
24
|
using EnumerableSet for EnumerableSet.AddressSet;
|
|
25
25
|
using EnumerableSet for EnumerableSet.UintSet;
|
|
26
26
|
using CustomRevert for bytes4;
|
|
@@ -135,7 +135,7 @@ abstract contract Entitled is IEntitlementBase, TokenOwnableBase {
|
|
|
135
135
|
address app = DependencyLib.getAppRegistry().getAppByClient(client);
|
|
136
136
|
if (app == address(0)) return false;
|
|
137
137
|
|
|
138
|
-
return
|
|
138
|
+
return _isAppEntitled(app, client, permission);
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
function _hasAnyBannedWallet(address[] memory wallets) internal view returns (bool) {
|
|
@@ -241,7 +241,27 @@ abstract contract AppAccountBase is
|
|
|
241
241
|
address client,
|
|
242
242
|
bytes32 permission
|
|
243
243
|
) internal view returns (bool) {
|
|
244
|
-
|
|
244
|
+
bytes32 appId = AppAccountStorage.getLayout().appIdByApp[module];
|
|
245
|
+
if (appId == EMPTY_UID) return false;
|
|
246
|
+
|
|
247
|
+
IAppRegistry registry = DependencyLib.getAppRegistry();
|
|
248
|
+
if (registry.isAppBanned(module)) return false;
|
|
249
|
+
|
|
250
|
+
IAppRegistry.App memory app = registry.getAppById(appId);
|
|
251
|
+
if (app.appId == EMPTY_UID) return false;
|
|
252
|
+
|
|
253
|
+
(bool hasClientAccess, , bool isGroupActive) = ExecutorStorage.hasGroupAccess(
|
|
254
|
+
app.appId,
|
|
255
|
+
client
|
|
256
|
+
);
|
|
257
|
+
if (!hasClientAccess || !isGroupActive) return false;
|
|
258
|
+
|
|
259
|
+
uint256 permissionsLength = app.permissions.length;
|
|
260
|
+
for (uint256 i; i < permissionsLength; ++i) {
|
|
261
|
+
if (app.permissions[i] == permission) return true;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return false;
|
|
245
265
|
}
|
|
246
266
|
|
|
247
267
|
/// @notice Gets the ID of the installed app.
|
|
@@ -37,27 +37,4 @@ library AppAccountStorage {
|
|
|
37
37
|
if (appId == EMPTY_UID) return app;
|
|
38
38
|
return DependencyLib.getAppRegistry().getAppById(appId);
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
function isAppEntitled(
|
|
42
|
-
address module,
|
|
43
|
-
address client,
|
|
44
|
-
bytes32 permission
|
|
45
|
-
) internal view returns (bool) {
|
|
46
|
-
IAppRegistry.App memory app = getApp(module);
|
|
47
|
-
|
|
48
|
-
if (app.appId == EMPTY_UID) return false;
|
|
49
|
-
|
|
50
|
-
(bool hasClientAccess, , bool isGroupActive) = ExecutorStorage.hasGroupAccess(
|
|
51
|
-
app.appId,
|
|
52
|
-
client
|
|
53
|
-
);
|
|
54
|
-
if (!hasClientAccess || !isGroupActive) return false;
|
|
55
|
-
|
|
56
|
-
uint256 permissionsLength = app.permissions.length;
|
|
57
|
-
for (uint256 i; i < permissionsLength; ++i) {
|
|
58
|
-
if (app.permissions[i] == permission) return true;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
40
|
}
|
|
@@ -84,7 +84,7 @@ abstract contract TippingBase is ITippingBase, PointsBase {
|
|
|
84
84
|
TipRecipientType.Member,
|
|
85
85
|
tipRequest.currency,
|
|
86
86
|
tipAmount,
|
|
87
|
-
tipRequest.tokenId
|
|
87
|
+
abi.encode(tipRequest.tokenId)
|
|
88
88
|
);
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -121,7 +121,7 @@ abstract contract TippingBase is ITippingBase, PointsBase {
|
|
|
121
121
|
TipRecipientType.Member,
|
|
122
122
|
params.currency,
|
|
123
123
|
tipAmount,
|
|
124
|
-
params.
|
|
124
|
+
params.metadata.data
|
|
125
125
|
);
|
|
126
126
|
|
|
127
127
|
emit Tip(
|
|
@@ -165,7 +165,7 @@ abstract contract TippingBase is ITippingBase, PointsBase {
|
|
|
165
165
|
TipRecipientType.Bot,
|
|
166
166
|
params.currency,
|
|
167
167
|
tipAmount,
|
|
168
|
-
|
|
168
|
+
params.metadata.data
|
|
169
169
|
);
|
|
170
170
|
}
|
|
171
171
|
|