@bananapus/core-v6 0.0.9 → 0.0.10
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/foundry.toml +0 -1
- package/package.json +2 -2
- package/src/JBChainlinkV3PriceFeed.sol +1 -5
- package/src/JBChainlinkV3SequencerPriceFeed.sol +1 -1
- package/src/JBController.sol +277 -277
- package/src/JBDeadline.sol +1 -1
- package/src/JBDirectory.sol +93 -93
- package/src/JBERC20.sol +43 -39
- package/src/JBFeelessAddresses.sol +12 -12
- package/src/JBFundAccessLimits.sol +82 -82
- package/src/JBMultiTerminal.sol +313 -313
- package/src/JBPermissions.sol +104 -100
- package/src/JBPrices.sol +68 -68
- package/src/JBProjects.sol +31 -31
- package/src/JBRulesets.sol +422 -422
- package/src/JBSplits.sol +116 -116
- package/src/JBTerminalStore.sol +651 -651
- package/src/JBTokens.sol +41 -41
- package/src/interfaces/IJBCashOutTerminal.sol +25 -7
- package/src/interfaces/IJBController.sol +78 -3
- package/src/interfaces/IJBDirectory.sol +25 -0
- package/src/interfaces/IJBFeeTerminal.sol +31 -0
- package/src/interfaces/IJBFeelessAddresses.sol +4 -0
- package/src/interfaces/IJBFundAccessLimits.sol +5 -0
- package/src/interfaces/IJBMigratable.sol +12 -8
- package/src/interfaces/IJBPayoutTerminal.sol +56 -9
- package/src/interfaces/IJBPermissions.sol +14 -7
- package/src/interfaces/IJBPermitTerminal.sol +4 -0
- package/src/interfaces/IJBPrices.sol +6 -0
- package/src/interfaces/IJBProjects.sol +8 -0
- package/src/interfaces/IJBRulesetApprovalHook.sol +1 -1
- package/src/interfaces/IJBRulesetDataHook.sol +23 -23
- package/src/interfaces/IJBRulesets.sol +54 -33
- package/src/interfaces/IJBSplits.sol +6 -0
- package/src/interfaces/IJBTerminal.sol +36 -0
- package/src/interfaces/IJBTerminalStore.sol +63 -63
- package/src/interfaces/IJBToken.sol +5 -5
- package/src/interfaces/IJBTokens.sol +50 -8
- package/test/TestDurationUnderflow.sol +3 -2
package/src/JBMultiTerminal.sol
CHANGED
|
@@ -183,173 +183,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
183
183
|
PERMIT2 = permit2;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
//*********************************************************************//
|
|
187
|
-
// ------------------------- external views -------------------------- //
|
|
188
|
-
//*********************************************************************//
|
|
189
|
-
|
|
190
|
-
/// @notice A project's accounting context for a token.
|
|
191
|
-
/// @dev See the `JBAccountingContext` struct for more information.
|
|
192
|
-
/// @param projectId The ID of the project to get token accounting context of.
|
|
193
|
-
/// @param token The token to check the accounting context of.
|
|
194
|
-
/// @return The token's accounting context for the token.
|
|
195
|
-
function accountingContextForTokenOf(
|
|
196
|
-
uint256 projectId,
|
|
197
|
-
address token
|
|
198
|
-
)
|
|
199
|
-
external
|
|
200
|
-
view
|
|
201
|
-
override
|
|
202
|
-
returns (JBAccountingContext memory)
|
|
203
|
-
{
|
|
204
|
-
return _accountingContextForTokenOf[projectId][token];
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/// @notice The tokens accepted by a project.
|
|
208
|
-
/// @param projectId The ID of the project to get the accepted tokens of.
|
|
209
|
-
/// @return tokenContexts The accounting contexts of the accepted tokens.
|
|
210
|
-
function accountingContextsOf(uint256 projectId) external view override returns (JBAccountingContext[] memory) {
|
|
211
|
-
return _accountingContextsOf[projectId];
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/// @notice Gets the total current surplus amount in this terminal for a project, in terms of a given currency.
|
|
215
|
-
/// @dev This total surplus only includes tokens that the project accepts (as returned by
|
|
216
|
-
/// `accountingContextsOf(...)`).
|
|
217
|
-
/// @param projectId The ID of the project to get the current total surplus of.
|
|
218
|
-
/// @param accountingContexts The accounting contexts to use to calculate the surplus. Pass an empty array to use
|
|
219
|
-
/// all of the project's accounting contexts.
|
|
220
|
-
/// @param decimals The number of decimals to include in the fixed point returned value.
|
|
221
|
-
/// @param currency The currency to express the returned value in terms of.
|
|
222
|
-
/// @return The current surplus amount the project has in this terminal, in terms of `currency` and with the
|
|
223
|
-
/// specified number of decimals.
|
|
224
|
-
function currentSurplusOf(
|
|
225
|
-
uint256 projectId,
|
|
226
|
-
JBAccountingContext[] memory accountingContexts,
|
|
227
|
-
uint256 decimals,
|
|
228
|
-
uint256 currency
|
|
229
|
-
)
|
|
230
|
-
external
|
|
231
|
-
view
|
|
232
|
-
override
|
|
233
|
-
returns (uint256)
|
|
234
|
-
{
|
|
235
|
-
return STORE.currentSurplusOf({
|
|
236
|
-
terminal: address(this),
|
|
237
|
-
projectId: projectId,
|
|
238
|
-
accountingContexts: accountingContexts.length != 0 ? accountingContexts : _accountingContextsOf[projectId],
|
|
239
|
-
decimals: decimals,
|
|
240
|
-
currency: currency
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/// @notice Fees that are being held for a project.
|
|
245
|
-
/// @dev Projects can temporarily hold fees and unlock them later by adding funds to the project's balance.
|
|
246
|
-
/// @dev Held fees can be processed at any time by this terminal's owner.
|
|
247
|
-
/// @param projectId The ID of the project that is holding fees.
|
|
248
|
-
/// @param token The token that the fees are held in.
|
|
249
|
-
function heldFeesOf(
|
|
250
|
-
uint256 projectId,
|
|
251
|
-
address token,
|
|
252
|
-
uint256 count
|
|
253
|
-
)
|
|
254
|
-
external
|
|
255
|
-
view
|
|
256
|
-
override
|
|
257
|
-
returns (JBFee[] memory heldFees)
|
|
258
|
-
{
|
|
259
|
-
// Keep a reference to the start index.
|
|
260
|
-
uint256 startIndex = _nextHeldFeeIndexOf[projectId][token];
|
|
261
|
-
|
|
262
|
-
// Get a reference to the number of held fees.
|
|
263
|
-
uint256 numberOfHeldFees = _heldFeesOf[projectId][token].length;
|
|
264
|
-
|
|
265
|
-
// If the start index is greater than or equal to the number of held fees, return 0.
|
|
266
|
-
if (startIndex >= numberOfHeldFees) return new JBFee[](0);
|
|
267
|
-
|
|
268
|
-
// If the start index plus the count is greater than the number of fees, set the count to the number of fees
|
|
269
|
-
if (startIndex + count > numberOfHeldFees) count = numberOfHeldFees - startIndex;
|
|
270
|
-
|
|
271
|
-
// Create a new array to hold the fees.
|
|
272
|
-
heldFees = new JBFee[](count);
|
|
273
|
-
|
|
274
|
-
// Copy the fees into the array.
|
|
275
|
-
for (uint256 i; i < count; i++) {
|
|
276
|
-
heldFees[i] = _heldFeesOf[projectId][token][startIndex + i];
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
//*********************************************************************//
|
|
281
|
-
// -------------------------- public views --------------------------- //
|
|
282
|
-
//*********************************************************************//
|
|
283
|
-
|
|
284
|
-
/// @notice Indicates whether this contract adheres to the specified interface.
|
|
285
|
-
/// @dev See {IERC165-supportsInterface}.
|
|
286
|
-
/// @param interfaceId The ID of the interface to check for adherence to.
|
|
287
|
-
/// @return A flag indicating if the provided interface ID is supported.
|
|
288
|
-
function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {
|
|
289
|
-
return interfaceId == type(IJBMultiTerminal).interfaceId || interfaceId == type(IJBPermissioned).interfaceId
|
|
290
|
-
|| interfaceId == type(IJBTerminal).interfaceId || interfaceId == type(IJBCashOutTerminal).interfaceId
|
|
291
|
-
|| interfaceId == type(IJBPayoutTerminal).interfaceId || interfaceId == type(IJBPermitTerminal).interfaceId
|
|
292
|
-
|| interfaceId == type(IJBFeeTerminal).interfaceId || interfaceId == type(IERC165).interfaceId;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
//*********************************************************************//
|
|
296
|
-
// -------------------------- internal views ------------------------- //
|
|
297
|
-
//*********************************************************************//
|
|
298
|
-
|
|
299
|
-
/// @notice Checks this terminal's balance of a specific token.
|
|
300
|
-
/// @param token The address of the token to get this terminal's balance of.
|
|
301
|
-
/// @return This terminal's balance.
|
|
302
|
-
function _balanceOf(address token) internal view returns (uint256) {
|
|
303
|
-
// If the `token` is native, get the native token balance.
|
|
304
|
-
return token == JBConstants.NATIVE_TOKEN ? address(this).balance : IERC20(token).balanceOf(address(this));
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/// @dev `ERC-2771` specifies the context as being a single address (20 bytes).
|
|
308
|
-
function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
|
|
309
|
-
return super._contextSuffixLength();
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/// @notice Returns the current controller of a project.
|
|
313
|
-
/// @param projectId The ID of the project to get the controller of.
|
|
314
|
-
/// @return controller The project's controller.
|
|
315
|
-
function _controllerOf(uint256 projectId) internal view returns (IJBController) {
|
|
316
|
-
return IJBController(address(DIRECTORY.controllerOf(projectId)));
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/// @notice Returns a flag indicating if interacting with an address should not incur fees.
|
|
320
|
-
/// @param addr The address to check.
|
|
321
|
-
/// @return A flag indicating if the address should not incur fees.
|
|
322
|
-
function _isFeeless(address addr) internal view returns (bool) {
|
|
323
|
-
return FEELESS_ADDRESSES.isFeeless(addr);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/// @notice The calldata. Preferred to use over `msg.data`.
|
|
327
|
-
/// @return calldata The `msg.data` of this call.
|
|
328
|
-
function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
|
|
329
|
-
return ERC2771Context._msgData();
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/// @notice The message's sender. Preferred to use over `msg.sender`.
|
|
333
|
-
/// @return sender The address which sent this call.
|
|
334
|
-
function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
|
|
335
|
-
return ERC2771Context._msgSender();
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/// @notice The owner of a project.
|
|
339
|
-
/// @param projectId The ID of the project to get the owner of.
|
|
340
|
-
/// @return The owner of the project.
|
|
341
|
-
function _ownerOf(uint256 projectId) internal view returns (address) {
|
|
342
|
-
return PROJECTS.ownerOf(projectId);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/// @notice The primary terminal of a project for a token.
|
|
346
|
-
/// @param projectId The ID of the project to get the primary terminal of.
|
|
347
|
-
/// @param token The token to get the primary terminal of.
|
|
348
|
-
/// @return The primary terminal of the project for the token.
|
|
349
|
-
function _primaryTerminalOf(uint256 projectId, address token) internal view returns (IJBTerminal) {
|
|
350
|
-
return DIRECTORY.primaryTerminalOf({projectId: projectId, token: token});
|
|
351
|
-
}
|
|
352
|
-
|
|
353
186
|
//*********************************************************************//
|
|
354
187
|
// ---------------------- external transactions ---------------------- //
|
|
355
188
|
//*********************************************************************//
|
|
@@ -938,7 +771,116 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
938
771
|
}
|
|
939
772
|
|
|
940
773
|
//*********************************************************************//
|
|
941
|
-
//
|
|
774
|
+
// ------------------------- external views -------------------------- //
|
|
775
|
+
//*********************************************************************//
|
|
776
|
+
|
|
777
|
+
/// @notice A project's accounting context for a token.
|
|
778
|
+
/// @dev See the `JBAccountingContext` struct for more information.
|
|
779
|
+
/// @param projectId The ID of the project to get token accounting context of.
|
|
780
|
+
/// @param token The token to check the accounting context of.
|
|
781
|
+
/// @return The token's accounting context for the token.
|
|
782
|
+
function accountingContextForTokenOf(
|
|
783
|
+
uint256 projectId,
|
|
784
|
+
address token
|
|
785
|
+
)
|
|
786
|
+
external
|
|
787
|
+
view
|
|
788
|
+
override
|
|
789
|
+
returns (JBAccountingContext memory)
|
|
790
|
+
{
|
|
791
|
+
return _accountingContextForTokenOf[projectId][token];
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/// @notice The tokens accepted by a project.
|
|
795
|
+
/// @param projectId The ID of the project to get the accepted tokens of.
|
|
796
|
+
/// @return tokenContexts The accounting contexts of the accepted tokens.
|
|
797
|
+
function accountingContextsOf(uint256 projectId) external view override returns (JBAccountingContext[] memory) {
|
|
798
|
+
return _accountingContextsOf[projectId];
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/// @notice Gets the total current surplus amount in this terminal for a project, in terms of a given currency.
|
|
802
|
+
/// @dev This total surplus only includes tokens that the project accepts (as returned by
|
|
803
|
+
/// `accountingContextsOf(...)`).
|
|
804
|
+
/// @param projectId The ID of the project to get the current total surplus of.
|
|
805
|
+
/// @param accountingContexts The accounting contexts to use to calculate the surplus. Pass an empty array to use
|
|
806
|
+
/// all of the project's accounting contexts.
|
|
807
|
+
/// @param decimals The number of decimals to include in the fixed point returned value.
|
|
808
|
+
/// @param currency The currency to express the returned value in terms of.
|
|
809
|
+
/// @return The current surplus amount the project has in this terminal, in terms of `currency` and with the
|
|
810
|
+
/// specified number of decimals.
|
|
811
|
+
function currentSurplusOf(
|
|
812
|
+
uint256 projectId,
|
|
813
|
+
JBAccountingContext[] memory accountingContexts,
|
|
814
|
+
uint256 decimals,
|
|
815
|
+
uint256 currency
|
|
816
|
+
)
|
|
817
|
+
external
|
|
818
|
+
view
|
|
819
|
+
override
|
|
820
|
+
returns (uint256)
|
|
821
|
+
{
|
|
822
|
+
return STORE.currentSurplusOf({
|
|
823
|
+
terminal: address(this),
|
|
824
|
+
projectId: projectId,
|
|
825
|
+
accountingContexts: accountingContexts.length != 0 ? accountingContexts : _accountingContextsOf[projectId],
|
|
826
|
+
decimals: decimals,
|
|
827
|
+
currency: currency
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/// @notice Fees that are being held for a project.
|
|
832
|
+
/// @dev Projects can temporarily hold fees and unlock them later by adding funds to the project's balance.
|
|
833
|
+
/// @dev Held fees can be processed at any time by this terminal's owner.
|
|
834
|
+
/// @param projectId The ID of the project that is holding fees.
|
|
835
|
+
/// @param token The token that the fees are held in.
|
|
836
|
+
function heldFeesOf(
|
|
837
|
+
uint256 projectId,
|
|
838
|
+
address token,
|
|
839
|
+
uint256 count
|
|
840
|
+
)
|
|
841
|
+
external
|
|
842
|
+
view
|
|
843
|
+
override
|
|
844
|
+
returns (JBFee[] memory heldFees)
|
|
845
|
+
{
|
|
846
|
+
// Keep a reference to the start index.
|
|
847
|
+
uint256 startIndex = _nextHeldFeeIndexOf[projectId][token];
|
|
848
|
+
|
|
849
|
+
// Get a reference to the number of held fees.
|
|
850
|
+
uint256 numberOfHeldFees = _heldFeesOf[projectId][token].length;
|
|
851
|
+
|
|
852
|
+
// If the start index is greater than or equal to the number of held fees, return 0.
|
|
853
|
+
if (startIndex >= numberOfHeldFees) return new JBFee[](0);
|
|
854
|
+
|
|
855
|
+
// If the start index plus the count is greater than the number of fees, set the count to the number of fees
|
|
856
|
+
if (startIndex + count > numberOfHeldFees) count = numberOfHeldFees - startIndex;
|
|
857
|
+
|
|
858
|
+
// Create a new array to hold the fees.
|
|
859
|
+
heldFees = new JBFee[](count);
|
|
860
|
+
|
|
861
|
+
// Copy the fees into the array.
|
|
862
|
+
for (uint256 i; i < count; i++) {
|
|
863
|
+
heldFees[i] = _heldFeesOf[projectId][token][startIndex + i];
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
//*********************************************************************//
|
|
868
|
+
// -------------------------- public views --------------------------- //
|
|
869
|
+
//*********************************************************************//
|
|
870
|
+
|
|
871
|
+
/// @notice Indicates whether this contract adheres to the specified interface.
|
|
872
|
+
/// @dev See {IERC165-supportsInterface}.
|
|
873
|
+
/// @param interfaceId The ID of the interface to check for adherence to.
|
|
874
|
+
/// @return A flag indicating if the provided interface ID is supported.
|
|
875
|
+
function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {
|
|
876
|
+
return interfaceId == type(IJBMultiTerminal).interfaceId || interfaceId == type(IJBPermissioned).interfaceId
|
|
877
|
+
|| interfaceId == type(IJBTerminal).interfaceId || interfaceId == type(IJBCashOutTerminal).interfaceId
|
|
878
|
+
|| interfaceId == type(IJBPayoutTerminal).interfaceId || interfaceId == type(IJBPermitTerminal).interfaceId
|
|
879
|
+
|| interfaceId == type(IJBFeeTerminal).interfaceId || interfaceId == type(IERC165).interfaceId;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
//*********************************************************************//
|
|
883
|
+
// ---------------------- internal transactions ---------------------- //
|
|
942
884
|
//*********************************************************************//
|
|
943
885
|
|
|
944
886
|
/// @notice Accepts an incoming token.
|
|
@@ -1233,119 +1175,48 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1233
1175
|
/// terminal's `pay` function.
|
|
1234
1176
|
/// @param terminal The terminal on which the project is expecting to receive payments.
|
|
1235
1177
|
/// @param projectId The ID of the project being paid.
|
|
1236
|
-
/// @param token The token being paid in.
|
|
1237
|
-
/// @param amount The amount being paid, as a fixed point number with the amount of decimals that the terminal's
|
|
1238
|
-
/// accounting context specifies.
|
|
1239
|
-
/// @param beneficiary The address to receive any platform tokens minted.
|
|
1240
|
-
/// @param metadata Additional metadata to include with the payment.
|
|
1241
|
-
function _efficientPay(
|
|
1242
|
-
IJBTerminal terminal,
|
|
1243
|
-
uint256 projectId,
|
|
1244
|
-
address token,
|
|
1245
|
-
uint256 amount,
|
|
1246
|
-
address beneficiary,
|
|
1247
|
-
bytes memory metadata
|
|
1248
|
-
)
|
|
1249
|
-
internal
|
|
1250
|
-
{
|
|
1251
|
-
if (terminal == IJBTerminal(address(this))) {
|
|
1252
|
-
_pay({
|
|
1253
|
-
projectId: projectId,
|
|
1254
|
-
token: token,
|
|
1255
|
-
amount: amount,
|
|
1256
|
-
payer: address(this),
|
|
1257
|
-
beneficiary: beneficiary,
|
|
1258
|
-
memo: "",
|
|
1259
|
-
metadata: metadata
|
|
1260
|
-
});
|
|
1261
|
-
} else {
|
|
1262
|
-
// Trigger any inherited pre-transfer logic.
|
|
1263
|
-
// Keep a reference to the amount that'll be paid as a `msg.value`.
|
|
1264
|
-
// slither-disable-next-line reentrancy-events
|
|
1265
|
-
uint256 payValue = _beforeTransferTo({to: address(terminal), token: token, amount: amount});
|
|
1266
|
-
|
|
1267
|
-
// Send the fee.
|
|
1268
|
-
// If this terminal's token is ETH, send it in msg.value.
|
|
1269
|
-
// slither-disable-next-line unused-return
|
|
1270
|
-
terminal.pay{value: payValue}({
|
|
1271
|
-
projectId: projectId,
|
|
1272
|
-
token: token,
|
|
1273
|
-
amount: amount,
|
|
1274
|
-
beneficiary: beneficiary,
|
|
1275
|
-
minReturnedTokens: 0,
|
|
1276
|
-
memo: "",
|
|
1277
|
-
metadata: metadata
|
|
1278
|
-
});
|
|
1279
|
-
}
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
/// @notice Fulfills a list of pay hook specifications.
|
|
1283
|
-
/// @param projectId The ID of the project being paid.
|
|
1284
|
-
/// @param specifications The pay hook specifications to be fulfilled.
|
|
1285
|
-
/// @param tokenAmount The amount of tokens that the project was paid.
|
|
1286
|
-
/// @param payer The address that sent the payment.
|
|
1287
|
-
/// @param ruleset The ruleset the payment is being accepted during.
|
|
1288
|
-
/// @param beneficiary The address which will receive any tokens that the payment yields.
|
|
1289
|
-
/// @param newlyIssuedTokenCount The amount of tokens that are being issued and sent to the beneificary.
|
|
1290
|
-
/// @param metadata Bytes to send along to the emitted event and pay hooks as applicable.
|
|
1291
|
-
function _fulfillPayHookSpecificationsFor(
|
|
1292
|
-
uint256 projectId,
|
|
1293
|
-
JBPayHookSpecification[] memory specifications,
|
|
1294
|
-
JBTokenAmount memory tokenAmount,
|
|
1295
|
-
address payer,
|
|
1296
|
-
JBRuleset memory ruleset,
|
|
1297
|
-
address beneficiary,
|
|
1298
|
-
uint256 newlyIssuedTokenCount,
|
|
1299
|
-
bytes memory metadata
|
|
1300
|
-
)
|
|
1301
|
-
internal
|
|
1302
|
-
{
|
|
1303
|
-
// Keep a reference to payment context for the pay hooks.
|
|
1304
|
-
JBAfterPayRecordedContext memory context = JBAfterPayRecordedContext({
|
|
1305
|
-
payer: payer,
|
|
1306
|
-
projectId: projectId,
|
|
1307
|
-
rulesetId: ruleset.id,
|
|
1308
|
-
amount: tokenAmount,
|
|
1309
|
-
forwardedAmount: tokenAmount,
|
|
1310
|
-
weight: ruleset.weight,
|
|
1311
|
-
newlyIssuedTokenCount: newlyIssuedTokenCount,
|
|
1312
|
-
beneficiary: beneficiary,
|
|
1313
|
-
hookMetadata: bytes(""),
|
|
1314
|
-
payerMetadata: metadata
|
|
1315
|
-
});
|
|
1316
|
-
|
|
1317
|
-
// Fulfill each specification through their pay hooks.
|
|
1318
|
-
for (uint256 i; i < specifications.length; i++) {
|
|
1319
|
-
// Set the specification being iterated on.
|
|
1320
|
-
JBPayHookSpecification memory specification = specifications[i];
|
|
1321
|
-
|
|
1322
|
-
// Pass the correct token `forwardedAmount` to the hook.
|
|
1323
|
-
context.forwardedAmount = JBTokenAmount({
|
|
1324
|
-
value: specification.amount,
|
|
1325
|
-
token: tokenAmount.token,
|
|
1326
|
-
decimals: tokenAmount.decimals,
|
|
1327
|
-
currency: tokenAmount.currency
|
|
1178
|
+
/// @param token The token being paid in.
|
|
1179
|
+
/// @param amount The amount being paid, as a fixed point number with the amount of decimals that the terminal's
|
|
1180
|
+
/// accounting context specifies.
|
|
1181
|
+
/// @param beneficiary The address to receive any platform tokens minted.
|
|
1182
|
+
/// @param metadata Additional metadata to include with the payment.
|
|
1183
|
+
function _efficientPay(
|
|
1184
|
+
IJBTerminal terminal,
|
|
1185
|
+
uint256 projectId,
|
|
1186
|
+
address token,
|
|
1187
|
+
uint256 amount,
|
|
1188
|
+
address beneficiary,
|
|
1189
|
+
bytes memory metadata
|
|
1190
|
+
)
|
|
1191
|
+
internal
|
|
1192
|
+
{
|
|
1193
|
+
if (terminal == IJBTerminal(address(this))) {
|
|
1194
|
+
_pay({
|
|
1195
|
+
projectId: projectId,
|
|
1196
|
+
token: token,
|
|
1197
|
+
amount: amount,
|
|
1198
|
+
payer: address(this),
|
|
1199
|
+
beneficiary: beneficiary,
|
|
1200
|
+
memo: "",
|
|
1201
|
+
metadata: metadata
|
|
1328
1202
|
});
|
|
1329
|
-
|
|
1330
|
-
// Pass the correct metadata from the data hook's specification.
|
|
1331
|
-
context.hookMetadata = specification.metadata;
|
|
1332
|
-
|
|
1203
|
+
} else {
|
|
1333
1204
|
// Trigger any inherited pre-transfer logic.
|
|
1334
1205
|
// Keep a reference to the amount that'll be paid as a `msg.value`.
|
|
1335
1206
|
// slither-disable-next-line reentrancy-events
|
|
1336
|
-
uint256 payValue = _beforeTransferTo({
|
|
1337
|
-
to: address(specification.hook), token: tokenAmount.token, amount: specification.amount
|
|
1338
|
-
});
|
|
1339
|
-
|
|
1340
|
-
// Fulfill the specification.
|
|
1341
|
-
// slither-disable-next-line reentrancy-events
|
|
1342
|
-
specification.hook.afterPayRecordedWith{value: payValue}(context);
|
|
1207
|
+
uint256 payValue = _beforeTransferTo({to: address(terminal), token: token, amount: amount});
|
|
1343
1208
|
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1209
|
+
// Send the fee.
|
|
1210
|
+
// If this terminal's token is ETH, send it in msg.value.
|
|
1211
|
+
// slither-disable-next-line unused-return
|
|
1212
|
+
terminal.pay{value: payValue}({
|
|
1213
|
+
projectId: projectId,
|
|
1214
|
+
token: token,
|
|
1215
|
+
amount: amount,
|
|
1216
|
+
beneficiary: beneficiary,
|
|
1217
|
+
minReturnedTokens: 0,
|
|
1218
|
+
memo: "",
|
|
1219
|
+
metadata: metadata
|
|
1349
1220
|
});
|
|
1350
1221
|
}
|
|
1351
1222
|
}
|
|
@@ -1437,6 +1308,77 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1437
1308
|
}
|
|
1438
1309
|
}
|
|
1439
1310
|
|
|
1311
|
+
/// @notice Fulfills a list of pay hook specifications.
|
|
1312
|
+
/// @param projectId The ID of the project being paid.
|
|
1313
|
+
/// @param specifications The pay hook specifications to be fulfilled.
|
|
1314
|
+
/// @param tokenAmount The amount of tokens that the project was paid.
|
|
1315
|
+
/// @param payer The address that sent the payment.
|
|
1316
|
+
/// @param ruleset The ruleset the payment is being accepted during.
|
|
1317
|
+
/// @param beneficiary The address which will receive any tokens that the payment yields.
|
|
1318
|
+
/// @param newlyIssuedTokenCount The amount of tokens that are being issued and sent to the beneificary.
|
|
1319
|
+
/// @param metadata Bytes to send along to the emitted event and pay hooks as applicable.
|
|
1320
|
+
function _fulfillPayHookSpecificationsFor(
|
|
1321
|
+
uint256 projectId,
|
|
1322
|
+
JBPayHookSpecification[] memory specifications,
|
|
1323
|
+
JBTokenAmount memory tokenAmount,
|
|
1324
|
+
address payer,
|
|
1325
|
+
JBRuleset memory ruleset,
|
|
1326
|
+
address beneficiary,
|
|
1327
|
+
uint256 newlyIssuedTokenCount,
|
|
1328
|
+
bytes memory metadata
|
|
1329
|
+
)
|
|
1330
|
+
internal
|
|
1331
|
+
{
|
|
1332
|
+
// Keep a reference to payment context for the pay hooks.
|
|
1333
|
+
JBAfterPayRecordedContext memory context = JBAfterPayRecordedContext({
|
|
1334
|
+
payer: payer,
|
|
1335
|
+
projectId: projectId,
|
|
1336
|
+
rulesetId: ruleset.id,
|
|
1337
|
+
amount: tokenAmount,
|
|
1338
|
+
forwardedAmount: tokenAmount,
|
|
1339
|
+
weight: ruleset.weight,
|
|
1340
|
+
newlyIssuedTokenCount: newlyIssuedTokenCount,
|
|
1341
|
+
beneficiary: beneficiary,
|
|
1342
|
+
hookMetadata: bytes(""),
|
|
1343
|
+
payerMetadata: metadata
|
|
1344
|
+
});
|
|
1345
|
+
|
|
1346
|
+
// Fulfill each specification through their pay hooks.
|
|
1347
|
+
for (uint256 i; i < specifications.length; i++) {
|
|
1348
|
+
// Set the specification being iterated on.
|
|
1349
|
+
JBPayHookSpecification memory specification = specifications[i];
|
|
1350
|
+
|
|
1351
|
+
// Pass the correct token `forwardedAmount` to the hook.
|
|
1352
|
+
context.forwardedAmount = JBTokenAmount({
|
|
1353
|
+
value: specification.amount,
|
|
1354
|
+
token: tokenAmount.token,
|
|
1355
|
+
decimals: tokenAmount.decimals,
|
|
1356
|
+
currency: tokenAmount.currency
|
|
1357
|
+
});
|
|
1358
|
+
|
|
1359
|
+
// Pass the correct metadata from the data hook's specification.
|
|
1360
|
+
context.hookMetadata = specification.metadata;
|
|
1361
|
+
|
|
1362
|
+
// Trigger any inherited pre-transfer logic.
|
|
1363
|
+
// Keep a reference to the amount that'll be paid as a `msg.value`.
|
|
1364
|
+
// slither-disable-next-line reentrancy-events
|
|
1365
|
+
uint256 payValue = _beforeTransferTo({
|
|
1366
|
+
to: address(specification.hook), token: tokenAmount.token, amount: specification.amount
|
|
1367
|
+
});
|
|
1368
|
+
|
|
1369
|
+
// Fulfill the specification.
|
|
1370
|
+
// slither-disable-next-line reentrancy-events
|
|
1371
|
+
specification.hook.afterPayRecordedWith{value: payValue}(context);
|
|
1372
|
+
|
|
1373
|
+
emit HookAfterRecordPay({
|
|
1374
|
+
hook: specification.hook,
|
|
1375
|
+
context: context,
|
|
1376
|
+
specificationAmount: specification.amount,
|
|
1377
|
+
caller: _msgSender()
|
|
1378
|
+
});
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1440
1382
|
/// @notice Pay a project with tokens.
|
|
1441
1383
|
/// @param projectId The ID of the project being paid.
|
|
1442
1384
|
/// @param token The address of the token which the project is being paid with.
|
|
@@ -1665,6 +1607,43 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1665
1607
|
/// `hook`, `projectId`, or `beneficiary`) to send funds to the `_msgSender()` which calls this function. This can
|
|
1666
1608
|
/// be used to incentivize calling this function.
|
|
1667
1609
|
/// @dev Payouts sent to addresses which aren't feeless incur the protocol fee.
|
|
1610
|
+
/// @notice Sends a payout to a split.
|
|
1611
|
+
/// @param split The split to pay.
|
|
1612
|
+
/// @param projectId The ID of the project the split was specified by.
|
|
1613
|
+
/// @param token The address of the token being paid out.
|
|
1614
|
+
/// @param amount The total amount that the split is being paid, as a fixed point number with the same number of
|
|
1615
|
+
/// decimals as this terminal.
|
|
1616
|
+
/// @return netPayoutAmount The amount sent to the split after subtracting fees.
|
|
1617
|
+
function _sendPayoutToSplit(
|
|
1618
|
+
JBSplit memory split,
|
|
1619
|
+
uint256 projectId,
|
|
1620
|
+
address token,
|
|
1621
|
+
uint256 amount
|
|
1622
|
+
)
|
|
1623
|
+
internal
|
|
1624
|
+
returns (uint256)
|
|
1625
|
+
{
|
|
1626
|
+
// Attempt to distribute this split.
|
|
1627
|
+
// slither-disable-next-line reentrancy-events
|
|
1628
|
+
try this.executePayout({
|
|
1629
|
+
split: split, projectId: projectId, token: token, amount: amount, originalMessageSender: _msgSender()
|
|
1630
|
+
}) returns (
|
|
1631
|
+
uint256 netPayoutAmount
|
|
1632
|
+
) {
|
|
1633
|
+
return netPayoutAmount;
|
|
1634
|
+
} catch (bytes memory failureReason) {
|
|
1635
|
+
emit PayoutReverted({
|
|
1636
|
+
projectId: projectId, split: split, amount: amount, reason: failureReason, caller: _msgSender()
|
|
1637
|
+
});
|
|
1638
|
+
|
|
1639
|
+
// Add balance back to the project.
|
|
1640
|
+
_recordAddedBalanceFor({projectId: projectId, token: token, amount: amount});
|
|
1641
|
+
|
|
1642
|
+
// Since the payout failed the netPayoutAmount is zero.
|
|
1643
|
+
return 0;
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1668
1647
|
/// @param projectId The ID of the project to send the payouts of.
|
|
1669
1648
|
/// @param token The token being paid out.
|
|
1670
1649
|
/// @param amount The number of terminal tokens to pay out, as a fixed point number with same number of decimals as
|
|
@@ -1762,43 +1741,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1762
1741
|
});
|
|
1763
1742
|
}
|
|
1764
1743
|
|
|
1765
|
-
/// @notice Sends a payout to a split.
|
|
1766
|
-
/// @param split The split to pay.
|
|
1767
|
-
/// @param projectId The ID of the project the split was specified by.
|
|
1768
|
-
/// @param token The address of the token being paid out.
|
|
1769
|
-
/// @param amount The total amount that the split is being paid, as a fixed point number with the same number of
|
|
1770
|
-
/// decimals as this terminal.
|
|
1771
|
-
/// @return netPayoutAmount The amount sent to the split after subtracting fees.
|
|
1772
|
-
function _sendPayoutToSplit(
|
|
1773
|
-
JBSplit memory split,
|
|
1774
|
-
uint256 projectId,
|
|
1775
|
-
address token,
|
|
1776
|
-
uint256 amount
|
|
1777
|
-
)
|
|
1778
|
-
internal
|
|
1779
|
-
returns (uint256)
|
|
1780
|
-
{
|
|
1781
|
-
// Attempt to distribute this split.
|
|
1782
|
-
// slither-disable-next-line reentrancy-events
|
|
1783
|
-
try this.executePayout({
|
|
1784
|
-
split: split, projectId: projectId, token: token, amount: amount, originalMessageSender: _msgSender()
|
|
1785
|
-
}) returns (
|
|
1786
|
-
uint256 netPayoutAmount
|
|
1787
|
-
) {
|
|
1788
|
-
return netPayoutAmount;
|
|
1789
|
-
} catch (bytes memory failureReason) {
|
|
1790
|
-
emit PayoutReverted({
|
|
1791
|
-
projectId: projectId, split: split, amount: amount, reason: failureReason, caller: _msgSender()
|
|
1792
|
-
});
|
|
1793
|
-
|
|
1794
|
-
// Add balance back to the project.
|
|
1795
|
-
_recordAddedBalanceFor({projectId: projectId, token: token, amount: amount});
|
|
1796
|
-
|
|
1797
|
-
// Since the payout failed the netPayoutAmount is zero.
|
|
1798
|
-
return 0;
|
|
1799
|
-
}
|
|
1800
|
-
}
|
|
1801
|
-
|
|
1802
1744
|
/// @notice Sends payouts to the payout splits group specified in a project's ruleset.
|
|
1803
1745
|
/// @param projectId The ID of the project to send the payouts of.
|
|
1804
1746
|
/// @param token The address of the token being paid out.
|
|
@@ -2021,4 +1963,62 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
2021
1963
|
_transferFrom({from: address(this), to: beneficiary, token: token, amount: netAmountPaidOut});
|
|
2022
1964
|
}
|
|
2023
1965
|
}
|
|
1966
|
+
|
|
1967
|
+
//*********************************************************************//
|
|
1968
|
+
// -------------------------- internal views ------------------------- //
|
|
1969
|
+
//*********************************************************************//
|
|
1970
|
+
|
|
1971
|
+
/// @notice Checks this terminal's balance of a specific token.
|
|
1972
|
+
/// @param token The address of the token to get this terminal's balance of.
|
|
1973
|
+
/// @return This terminal's balance.
|
|
1974
|
+
function _balanceOf(address token) internal view returns (uint256) {
|
|
1975
|
+
// If the `token` is native, get the native token balance.
|
|
1976
|
+
return token == JBConstants.NATIVE_TOKEN ? address(this).balance : IERC20(token).balanceOf(address(this));
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1979
|
+
/// @dev `ERC-2771` specifies the context as being a single address (20 bytes).
|
|
1980
|
+
function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
|
|
1981
|
+
return super._contextSuffixLength();
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
/// @notice Returns the current controller of a project.
|
|
1985
|
+
/// @param projectId The ID of the project to get the controller of.
|
|
1986
|
+
/// @return controller The project's controller.
|
|
1987
|
+
function _controllerOf(uint256 projectId) internal view returns (IJBController) {
|
|
1988
|
+
return IJBController(address(DIRECTORY.controllerOf(projectId)));
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1991
|
+
/// @notice Returns a flag indicating if interacting with an address should not incur fees.
|
|
1992
|
+
/// @param addr The address to check.
|
|
1993
|
+
/// @return A flag indicating if the address should not incur fees.
|
|
1994
|
+
function _isFeeless(address addr) internal view returns (bool) {
|
|
1995
|
+
return FEELESS_ADDRESSES.isFeeless(addr);
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
/// @notice The calldata. Preferred to use over `msg.data`.
|
|
1999
|
+
/// @return calldata The `msg.data` of this call.
|
|
2000
|
+
function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
|
|
2001
|
+
return ERC2771Context._msgData();
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
/// @notice The message's sender. Preferred to use over `msg.sender`.
|
|
2005
|
+
/// @return sender The address which sent this call.
|
|
2006
|
+
function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
|
|
2007
|
+
return ERC2771Context._msgSender();
|
|
2008
|
+
}
|
|
2009
|
+
|
|
2010
|
+
/// @notice The owner of a project.
|
|
2011
|
+
/// @param projectId The ID of the project to get the owner of.
|
|
2012
|
+
/// @return The owner of the project.
|
|
2013
|
+
function _ownerOf(uint256 projectId) internal view returns (address) {
|
|
2014
|
+
return PROJECTS.ownerOf(projectId);
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
/// @notice The primary terminal of a project for a token.
|
|
2018
|
+
/// @param projectId The ID of the project to get the primary terminal of.
|
|
2019
|
+
/// @param token The token to get the primary terminal of.
|
|
2020
|
+
/// @return The primary terminal of the project for the token.
|
|
2021
|
+
function _primaryTerminalOf(uint256 projectId, address token) internal view returns (IJBTerminal) {
|
|
2022
|
+
return DIRECTORY.primaryTerminalOf({projectId: projectId, token: token});
|
|
2023
|
+
}
|
|
2024
2024
|
}
|