@towns-protocol/contracts 0.0.366 → 0.0.368
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/src/apps/facets/registry/AppRegistryBase.sol +2 -1
- package/src/apps/helpers/ISimpleApp.sol +26 -1
- package/src/apps/helpers/SimpleApp.sol +22 -1
- package/src/apps/helpers/SimpleAppStorage.sol +1 -0
- package/src/spaces/facets/membership/MembershipBase.sol +19 -22
- package/src/spaces/facets/membership/MembershipStorage.sol +2 -3
- package/src/spaces/facets/membership/join/MembershipJoin.sol +5 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@towns-protocol/contracts",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.368",
|
|
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.368",
|
|
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": "bb014c92cd91d742be6ea53ac56027ec90e4d345"
|
|
61
61
|
}
|
|
@@ -137,7 +137,8 @@ abstract contract AppRegistryBase is IAppRegistryBase, SchemaBase, AttestationBa
|
|
|
137
137
|
params.name,
|
|
138
138
|
params.permissions,
|
|
139
139
|
params.installPrice,
|
|
140
|
-
duration
|
|
140
|
+
duration,
|
|
141
|
+
params.client
|
|
141
142
|
);
|
|
142
143
|
|
|
143
144
|
version = _registerApp(ITownsApp(app), params.client);
|
|
@@ -14,6 +14,18 @@ interface ISimpleAppBase {
|
|
|
14
14
|
/// @notice Thrown when there is no balance to withdraw
|
|
15
15
|
error NoBalanceToWithdraw();
|
|
16
16
|
|
|
17
|
+
/// @notice Thrown when the currency address is the zero address
|
|
18
|
+
error InvalidAddressInput();
|
|
19
|
+
|
|
20
|
+
/// @notice Thrown when the amount is zero
|
|
21
|
+
error InvalidAmount();
|
|
22
|
+
|
|
23
|
+
/// @notice Thrown when the caller is not allowed
|
|
24
|
+
error InvalidCaller();
|
|
25
|
+
|
|
26
|
+
/// @notice Thrown when the currency is invalid
|
|
27
|
+
error InvalidCurrency();
|
|
28
|
+
|
|
17
29
|
/// @notice Emitted when the app is withdrawn
|
|
18
30
|
/// @param recipient The address that received the withdrawal
|
|
19
31
|
/// @param amount The amount of tokens withdrawn
|
|
@@ -27,6 +39,12 @@ interface ISimpleAppBase {
|
|
|
27
39
|
/// @notice Emitted when permissions are updated
|
|
28
40
|
/// @param permissions The new permissions
|
|
29
41
|
event PermissionsUpdated(bytes32[] permissions);
|
|
42
|
+
|
|
43
|
+
/// @notice Emitted when the currency is sent
|
|
44
|
+
/// @param recipient The address that received the currency
|
|
45
|
+
/// @param currency The currency that was sent
|
|
46
|
+
/// @param amount The amount of currency that was sent
|
|
47
|
+
event SendCurrency(address indexed recipient, address indexed currency, uint256 amount);
|
|
30
48
|
}
|
|
31
49
|
|
|
32
50
|
interface ISimpleApp is ISimpleAppBase {
|
|
@@ -34,6 +52,12 @@ interface ISimpleApp is ISimpleAppBase {
|
|
|
34
52
|
/// @param recipient The address to withdraw the ETH to
|
|
35
53
|
function withdrawETH(address recipient) external;
|
|
36
54
|
|
|
55
|
+
/// @notice Sends the currency balance of the app to the recipient
|
|
56
|
+
/// @param recipient The address to send the currency to
|
|
57
|
+
/// @param currency The currency to send
|
|
58
|
+
/// @param amount The amount of currency to send
|
|
59
|
+
function sendCurrency(address recipient, address currency, uint256 amount) external;
|
|
60
|
+
|
|
37
61
|
/// @notice Updates the pricing of the app
|
|
38
62
|
/// @param installPrice The new install price
|
|
39
63
|
/// @param accessDuration The new access duration
|
|
@@ -54,6 +78,7 @@ interface ISimpleApp is ISimpleAppBase {
|
|
|
54
78
|
string calldata appId,
|
|
55
79
|
bytes32[] calldata permissions,
|
|
56
80
|
uint256 installPrice,
|
|
57
|
-
uint48 accessDuration
|
|
81
|
+
uint48 accessDuration,
|
|
82
|
+
address client
|
|
58
83
|
) external;
|
|
59
84
|
}
|
|
@@ -28,7 +28,8 @@ contract SimpleApp is ISimpleApp, Ownable, BaseApp, Initializable {
|
|
|
28
28
|
string calldata appId,
|
|
29
29
|
bytes32[] calldata permissions,
|
|
30
30
|
uint256 installPrice,
|
|
31
|
-
uint48 accessDuration
|
|
31
|
+
uint48 accessDuration,
|
|
32
|
+
address client
|
|
32
33
|
) external initializer {
|
|
33
34
|
_setOwner(owner);
|
|
34
35
|
SimpleAppStorage.Layout storage $ = SimpleAppStorage.getLayout();
|
|
@@ -36,6 +37,7 @@ contract SimpleApp is ISimpleApp, Ownable, BaseApp, Initializable {
|
|
|
36
37
|
$.permissions = permissions;
|
|
37
38
|
$.installPrice = installPrice;
|
|
38
39
|
$.accessDuration = accessDuration;
|
|
40
|
+
$.client = client;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
/// @inheritdoc ISimpleApp
|
|
@@ -50,6 +52,19 @@ contract SimpleApp is ISimpleApp, Ownable, BaseApp, Initializable {
|
|
|
50
52
|
emit Withdrawal(recipient, balance);
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
function sendCurrency(address recipient, address currency, uint256 amount) external {
|
|
56
|
+
_checkAllowed();
|
|
57
|
+
|
|
58
|
+
if (recipient == address(0)) ZeroAddress.selector.revertWith();
|
|
59
|
+
if (currency == address(0)) currency = CurrencyTransfer.NATIVE_TOKEN;
|
|
60
|
+
else if (currency.code.length == 0) InvalidCurrency.selector.revertWith();
|
|
61
|
+
if (amount == 0) InvalidAmount.selector.revertWith();
|
|
62
|
+
|
|
63
|
+
CurrencyTransfer.transferCurrency(currency, address(this), recipient, amount);
|
|
64
|
+
|
|
65
|
+
emit SendCurrency(recipient, currency, amount);
|
|
66
|
+
}
|
|
67
|
+
|
|
53
68
|
/// @inheritdoc ISimpleApp
|
|
54
69
|
function updatePricing(uint256 installPrice, uint48 accessDuration) external onlyOwner {
|
|
55
70
|
SimpleAppStorage.Layout storage $ = SimpleAppStorage.getLayout();
|
|
@@ -99,4 +114,10 @@ contract SimpleApp is ISimpleApp, Ownable, BaseApp, Initializable {
|
|
|
99
114
|
function _moduleOwner() internal view override returns (address) {
|
|
100
115
|
return owner();
|
|
101
116
|
}
|
|
117
|
+
|
|
118
|
+
function _checkAllowed() internal view {
|
|
119
|
+
if (msg.sender == owner()) return;
|
|
120
|
+
if (msg.sender == SimpleAppStorage.getLayout().client) return;
|
|
121
|
+
InvalidCaller.selector.revertWith();
|
|
122
|
+
}
|
|
102
123
|
}
|
|
@@ -20,19 +20,19 @@ abstract contract MembershipBase is IMembershipBase {
|
|
|
20
20
|
using SafeTransferLib for address;
|
|
21
21
|
|
|
22
22
|
function __MembershipBase_init(Membership memory info, address spaceFactory) internal {
|
|
23
|
-
MembershipStorage.Layout storage
|
|
23
|
+
MembershipStorage.Layout storage $ = MembershipStorage.layout();
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
$.spaceFactory = spaceFactory;
|
|
26
|
+
$.pricingModule = info.pricingModule;
|
|
27
|
+
$.membershipCurrency = CurrencyTransfer.NATIVE_TOKEN;
|
|
28
|
+
$.membershipMaxSupply = info.maxSupply;
|
|
29
29
|
|
|
30
30
|
if (info.freeAllocation > 0) {
|
|
31
31
|
_verifyFreeAllocation(info.freeAllocation);
|
|
32
|
-
|
|
32
|
+
$.freeAllocation = info.freeAllocation;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
$.freeAllocationEnabled = true;
|
|
36
36
|
|
|
37
37
|
if (info.price > 0) {
|
|
38
38
|
_verifyPrice(info.price);
|
|
@@ -41,7 +41,7 @@ abstract contract MembershipBase is IMembershipBase {
|
|
|
41
41
|
|
|
42
42
|
if (info.duration > 0) {
|
|
43
43
|
_verifyDuration(info.duration);
|
|
44
|
-
|
|
44
|
+
$.membershipDuration = info.duration;
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -75,13 +75,13 @@ abstract contract MembershipBase is IMembershipBase {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
function _transferIn(address from, uint256 amount) internal returns (uint256) {
|
|
78
|
-
MembershipStorage.Layout storage
|
|
78
|
+
MembershipStorage.Layout storage $ = MembershipStorage.layout();
|
|
79
79
|
|
|
80
80
|
// get the currency being used for membership
|
|
81
81
|
address currency = _getMembershipCurrency();
|
|
82
82
|
|
|
83
83
|
if (currency == CurrencyTransfer.NATIVE_TOKEN) {
|
|
84
|
-
|
|
84
|
+
$.tokenBalance += amount;
|
|
85
85
|
return amount;
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -94,7 +94,7 @@ abstract contract MembershipBase is IMembershipBase {
|
|
|
94
94
|
uint256 finalAmount = balanceAfter - balanceBefore;
|
|
95
95
|
if (finalAmount != amount) Membership__InsufficientPayment.selector.revertWith();
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
$.tokenBalance += finalAmount;
|
|
98
98
|
return finalAmount;
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -162,14 +162,12 @@ abstract contract MembershipBase is IMembershipBase {
|
|
|
162
162
|
function _getMembershipPrice(
|
|
163
163
|
uint256 totalSupply
|
|
164
164
|
) internal view virtual returns (uint256 membershipPrice) {
|
|
165
|
-
// get free allocation
|
|
166
|
-
uint256 freeAllocation = _getMembershipFreeAllocation();
|
|
167
165
|
address pricingModule = _getPricingModule();
|
|
168
|
-
|
|
169
166
|
IPlatformRequirements platform = _getPlatformRequirements();
|
|
170
|
-
|
|
171
167
|
if (pricingModule == address(0)) return platform.getMembershipFee();
|
|
172
168
|
|
|
169
|
+
// get free allocation
|
|
170
|
+
uint256 freeAllocation = _getMembershipFreeAllocation();
|
|
173
171
|
membershipPrice = IMembershipPricing(pricingModule).getPrice(freeAllocation, totalSupply);
|
|
174
172
|
uint256 minPrice = platform.getMembershipMinPrice();
|
|
175
173
|
if (membershipPrice < minPrice) return platform.getMembershipFee();
|
|
@@ -183,11 +181,11 @@ abstract contract MembershipBase is IMembershipBase {
|
|
|
183
181
|
uint256 tokenId,
|
|
184
182
|
uint256 totalSupply
|
|
185
183
|
) internal view returns (uint256) {
|
|
186
|
-
MembershipStorage.Layout storage
|
|
184
|
+
MembershipStorage.Layout storage $ = MembershipStorage.layout();
|
|
187
185
|
IPlatformRequirements platform = _getPlatformRequirements();
|
|
188
186
|
|
|
189
187
|
uint256 minFee = platform.getMembershipFee();
|
|
190
|
-
uint256 renewalPrice =
|
|
188
|
+
uint256 renewalPrice = $.renewalPriceByTokenId[tokenId];
|
|
191
189
|
|
|
192
190
|
if (renewalPrice != 0) return FixedPointMathLib.max(renewalPrice, minFee);
|
|
193
191
|
|
|
@@ -207,16 +205,15 @@ abstract contract MembershipBase is IMembershipBase {
|
|
|
207
205
|
}
|
|
208
206
|
|
|
209
207
|
function _setMembershipFreeAllocation(uint256 newAllocation) internal {
|
|
210
|
-
MembershipStorage.Layout storage
|
|
211
|
-
|
|
212
|
-
ds.freeAllocationEnabled = true;
|
|
208
|
+
MembershipStorage.Layout storage $ = MembershipStorage.layout();
|
|
209
|
+
($.freeAllocation, $.freeAllocationEnabled) = (newAllocation, true);
|
|
213
210
|
emit MembershipFreeAllocationUpdated(newAllocation);
|
|
214
211
|
}
|
|
215
212
|
|
|
216
213
|
function _getMembershipFreeAllocation() internal view returns (uint256) {
|
|
217
|
-
MembershipStorage.Layout storage
|
|
214
|
+
MembershipStorage.Layout storage $ = MembershipStorage.layout();
|
|
218
215
|
|
|
219
|
-
if (
|
|
216
|
+
if ($.freeAllocationEnabled) return $.freeAllocation;
|
|
220
217
|
|
|
221
218
|
return _getPlatformRequirements().getMembershipMintLimit();
|
|
222
219
|
}
|
|
@@ -31,10 +31,9 @@ library MembershipStorage {
|
|
|
31
31
|
bool freeAllocationEnabled;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
function layout() internal pure returns (Layout storage
|
|
35
|
-
bytes32 slot = STORAGE_SLOT;
|
|
34
|
+
function layout() internal pure returns (Layout storage $) {
|
|
36
35
|
assembly {
|
|
37
|
-
|
|
36
|
+
$.slot := STORAGE_SLOT
|
|
38
37
|
}
|
|
39
38
|
}
|
|
40
39
|
}
|
|
@@ -74,7 +74,6 @@ abstract contract MembershipJoin is
|
|
|
74
74
|
uint256 totalSupply = _totalSupply();
|
|
75
75
|
uint256 membershipPrice = _getMembershipPrice(totalSupply);
|
|
76
76
|
uint256 freeAllocation = _getMembershipFreeAllocation();
|
|
77
|
-
uint256 prepaidSupply = _getPrepaidSupply();
|
|
78
77
|
|
|
79
78
|
joinDetails.basePrice = membershipPrice;
|
|
80
79
|
if (freeAllocation > totalSupply) {
|
|
@@ -82,14 +81,14 @@ abstract contract MembershipJoin is
|
|
|
82
81
|
}
|
|
83
82
|
|
|
84
83
|
// Check if this is a free join due to prepaid supply
|
|
84
|
+
uint256 prepaidSupply = _getPrepaidSupply();
|
|
85
85
|
if (prepaidSupply > 0) {
|
|
86
86
|
joinDetails.isPrepaid = true;
|
|
87
87
|
return joinDetails;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
// Regular paid join
|
|
91
|
-
joinDetails.amountDue = membershipPrice;
|
|
92
|
-
joinDetails.shouldCharge = true;
|
|
91
|
+
(joinDetails.amountDue, joinDetails.shouldCharge) = (membershipPrice, true);
|
|
93
92
|
}
|
|
94
93
|
|
|
95
94
|
/// @notice Handles the process of joining a space
|
|
@@ -144,9 +143,7 @@ abstract contract MembershipJoin is
|
|
|
144
143
|
}
|
|
145
144
|
|
|
146
145
|
// Consume prepaid membership if applicable
|
|
147
|
-
if (joinDetails.isPrepaid)
|
|
148
|
-
_reducePrepay(1);
|
|
149
|
-
}
|
|
146
|
+
if (joinDetails.isPrepaid) _reducePrepay(1);
|
|
150
147
|
|
|
151
148
|
_validateUserReferral(receiver, referral);
|
|
152
149
|
|
|
@@ -186,10 +183,8 @@ abstract contract MembershipJoin is
|
|
|
186
183
|
}
|
|
187
184
|
|
|
188
185
|
function _validateUserReferral(address receiver, ReferralTypes memory referral) internal view {
|
|
189
|
-
if (referral.userReferral
|
|
190
|
-
|
|
191
|
-
Membership__InvalidAddress.selector.revertWith();
|
|
192
|
-
}
|
|
186
|
+
if (referral.userReferral == receiver || referral.userReferral == msg.sender) {
|
|
187
|
+
Membership__InvalidAddress.selector.revertWith();
|
|
193
188
|
}
|
|
194
189
|
}
|
|
195
190
|
|