@bananapus/core-v6 0.0.48 → 0.0.49
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 +1 -0
- package/package.json +1 -1
- package/src/libraries/JBPayoutSplitGroupLib.sol +26 -13
package/foundry.toml
CHANGED
package/package.json
CHANGED
|
@@ -88,10 +88,6 @@ library JBPayoutSplitGroupLib {
|
|
|
88
88
|
// Native vs ERC-20 governs the transfer mechanism (push via msg.value vs allowance pull).
|
|
89
89
|
bool isNative = token == JBConstants.NATIVE_TOKEN;
|
|
90
90
|
|
|
91
|
-
// Snapshot the relevant balance before the hook call. The post-call delta tells us how much the hook
|
|
92
|
-
// actually took, regardless of whether it pulled the full allowance, partially pulled, or reverted.
|
|
93
|
-
uint256 balanceBefore = isNative ? address(this).balance : IERC20(token).balanceOf(address(this));
|
|
94
|
-
|
|
95
91
|
// Build the hook context inline so the terminal call site doesn't have to. `decimals` is looked up from
|
|
96
92
|
// the terminal store's recorded accounting context for this (projectId, token) pair.
|
|
97
93
|
JBSplitHookContext memory context = JBSplitHookContext({
|
|
@@ -113,16 +109,33 @@ library JBPayoutSplitGroupLib {
|
|
|
113
109
|
}
|
|
114
110
|
|
|
115
111
|
// Wrap the hook call in try/catch so a reverting hook does not bubble out. On revert no tokens leave
|
|
116
|
-
// this contract (transferFrom inside the hook is rolled back; pushed ETH is returned)
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
112
|
+
// this contract (transferFrom inside the hook is rolled back; pushed ETH is returned). The success
|
|
113
|
+
// flag drives the native-ETH `sent` computation below — we cannot use a balance delta because the
|
|
114
|
+
// hook may reenter into this terminal (pay/cashOut/etc.) and shift our balance independently of its
|
|
115
|
+
// own consumption.
|
|
116
|
+
bool hookOk;
|
|
117
|
+
try split.hook.processSplitWith{value: payValue}(context) {
|
|
118
|
+
hookOk = true;
|
|
119
|
+
} catch {}
|
|
123
120
|
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
if (isNative) {
|
|
122
|
+
// Native ETH is pushed via `value:`. There is no on-the-fly "give some back" mechanism — a
|
|
123
|
+
// successful hook consumed exactly `netPayoutAmount`; a reverting hook consumed 0 (the EVM
|
|
124
|
+
// refunds the value on revert). Any side-effects the hook produced via reentrant terminal
|
|
125
|
+
// calls (pay/addToBalance/cashOut) are recorded through those calls' own bookkeeping and must
|
|
126
|
+
// not bleed into this split's consumption accounting.
|
|
127
|
+
sent = hookOk ? netPayoutAmount : 0;
|
|
128
|
+
} else {
|
|
129
|
+
// ERC-20 hooks pull via `transferFrom` against the allowance we granted. The allowance delta
|
|
130
|
+
// is the only consumption measure that is robust against reentrant balance manipulation: the
|
|
131
|
+
// hook cannot raise its own allowance, and any pull on this allowance reduces it 1:1 with
|
|
132
|
+
// what the hook actually received. Reentrant flows through other paths use independent
|
|
133
|
+
// allowances/values and so cannot inflate this measurement.
|
|
134
|
+
sent = netPayoutAmount - IERC20(token).allowance({owner: address(this), spender: address(split.hook)});
|
|
135
|
+
|
|
136
|
+
// Revoke any unconsumed ERC-20 allowance immediately after the call so the hook can never pull later.
|
|
137
|
+
SafeERC20.forceApprove({token: IERC20(token), spender: address(split.hook), value: 0});
|
|
138
|
+
}
|
|
126
139
|
|
|
127
140
|
// If the hook took less than offered, refund the proportional gross portion to the project's balance.
|
|
128
141
|
// refund = amount * (netPayoutAmount - sent) / netPayoutAmount. For full consumption this branch is
|