@bananapus/suckers-v6 0.0.66 → 0.0.67
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 +1 -1
- package/src/JBArbitrumSucker.sol +1 -1
- package/src/JBBaseSucker.sol +1 -1
- package/src/JBCCIPSucker.sol +1 -1
- package/src/JBOptimismSucker.sol +1 -1
- package/src/JBSucker.sol +62 -4
- package/src/JBSuckerRegistry.sol +43 -37
- package/src/interfaces/IJBSucker.sol +23 -0
- package/src/structs/JBPeerChainValue.sol +15 -0
package/package.json
CHANGED
package/src/JBArbitrumSucker.sol
CHANGED
|
@@ -81,7 +81,7 @@ contract JBArbitrumSucker is JBSucker, IJBArbitrumSucker {
|
|
|
81
81
|
|
|
82
82
|
/// @notice Returns the chain on which the peer is located.
|
|
83
83
|
/// @return chainId of the peer.
|
|
84
|
-
function peerChainId()
|
|
84
|
+
function peerChainId() public view virtual override returns (uint256) {
|
|
85
85
|
uint256 chainId = block.chainid;
|
|
86
86
|
if (chainId == ARBChains.ETH_CHAINID) return ARBChains.ARB_CHAINID;
|
|
87
87
|
if (chainId == ARBChains.ARB_CHAINID) return ARBChains.ETH_CHAINID;
|
package/src/JBBaseSucker.sol
CHANGED
|
@@ -40,7 +40,7 @@ contract JBBaseSucker is JBOptimismSucker {
|
|
|
40
40
|
|
|
41
41
|
/// @notice Returns the chain on which the peer is located.
|
|
42
42
|
/// @return chainId of the peer.
|
|
43
|
-
function peerChainId()
|
|
43
|
+
function peerChainId() public view virtual override returns (uint256) {
|
|
44
44
|
uint256 chainId = block.chainid;
|
|
45
45
|
if (chainId == 1) return 8453;
|
|
46
46
|
if (chainId == 8453) return 1;
|
package/src/JBCCIPSucker.sol
CHANGED
|
@@ -119,7 +119,7 @@ contract JBCCIPSucker is JBSucker, IAny2EVMMessageReceiver {
|
|
|
119
119
|
|
|
120
120
|
/// @notice Returns the chain on which the peer is located.
|
|
121
121
|
/// @return chainId The chain ID of the peer.
|
|
122
|
-
function peerChainId()
|
|
122
|
+
function peerChainId() public view virtual override returns (uint256 chainId) {
|
|
123
123
|
return REMOTE_CHAIN_ID;
|
|
124
124
|
}
|
|
125
125
|
|
package/src/JBOptimismSucker.sol
CHANGED
|
@@ -64,7 +64,7 @@ contract JBOptimismSucker is JBSucker, IJBOptimismSucker {
|
|
|
64
64
|
|
|
65
65
|
/// @notice Returns the chain on which the peer is located.
|
|
66
66
|
/// @return chainId of the peer.
|
|
67
|
-
function peerChainId()
|
|
67
|
+
function peerChainId() public view virtual override returns (uint256) {
|
|
68
68
|
uint256 chainId = block.chainid;
|
|
69
69
|
if (chainId == 1) return 10;
|
|
70
70
|
if (chainId == 10) return 1;
|
package/src/JBSucker.sol
CHANGED
|
@@ -40,6 +40,7 @@ import {JBDenominatedAmount} from "./structs/JBDenominatedAmount.sol";
|
|
|
40
40
|
import {JBInboxTreeRoot} from "./structs/JBInboxTreeRoot.sol";
|
|
41
41
|
import {JBMessageRoot} from "./structs/JBMessageRoot.sol";
|
|
42
42
|
import {JBOutboxTree} from "./structs/JBOutboxTree.sol";
|
|
43
|
+
import {JBPeerChainValue} from "./structs/JBPeerChainValue.sol";
|
|
43
44
|
import {JBRemoteToken} from "./structs/JBRemoteToken.sol";
|
|
44
45
|
import {JBTokenMapping} from "./structs/JBTokenMapping.sol";
|
|
45
46
|
|
|
@@ -773,10 +774,6 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
|
|
|
773
774
|
return _outboxOf[token];
|
|
774
775
|
}
|
|
775
776
|
|
|
776
|
-
/// @notice Returns the chain on which the peer is located.
|
|
777
|
-
/// @return chain ID of the peer.
|
|
778
|
-
function peerChainId() external view virtual returns (uint256);
|
|
779
|
-
|
|
780
777
|
/// @notice The peer chain balance, converted from the source denomination to the requested currency and decimal
|
|
781
778
|
/// precision using the local JBPrices oracle.
|
|
782
779
|
/// @param decimals The decimal precision for the returned value.
|
|
@@ -792,6 +789,28 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
|
|
|
792
789
|
});
|
|
793
790
|
}
|
|
794
791
|
|
|
792
|
+
/// @notice The peer chain balance bundled with the peer chain ID and snapshot freshness key.
|
|
793
|
+
/// @dev Lets aggregators (e.g. `JBSuckerRegistry`) read the value, the peer chain it belongs to, and its
|
|
794
|
+
/// freshness in one call instead of three separate staticcalls. The `value` is identical to
|
|
795
|
+
/// `peerChainBalanceOf`.
|
|
796
|
+
/// @param decimals The decimal precision for the returned value.
|
|
797
|
+
/// @param currency The currency to normalize to (e.g. `uint256(uint160(JBConstants.NATIVE_TOKEN))` for ETH).
|
|
798
|
+
/// @return A `JBPeerChainValue` with the converted balance, peer chain ID, and snapshot freshness key.
|
|
799
|
+
function peerChainBalanceValueOf(
|
|
800
|
+
uint256 decimals,
|
|
801
|
+
uint256 currency
|
|
802
|
+
)
|
|
803
|
+
external
|
|
804
|
+
view
|
|
805
|
+
returns (JBPeerChainValue memory)
|
|
806
|
+
{
|
|
807
|
+
return JBPeerChainValue({
|
|
808
|
+
value: _convertPeerValue({source: _peerChainBalance, decimals: decimals, currency: currency}),
|
|
809
|
+
peerChainId: peerChainId(),
|
|
810
|
+
snapshotTimestamp: snapshotTimestamp
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
|
|
795
814
|
/// @notice The peer chain surplus, converted from the source denomination to the requested currency and decimal
|
|
796
815
|
/// precision using the local JBPrices oracle.
|
|
797
816
|
/// @param decimals The decimal precision for the returned value.
|
|
@@ -807,6 +826,39 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
|
|
|
807
826
|
});
|
|
808
827
|
}
|
|
809
828
|
|
|
829
|
+
/// @notice The peer chain surplus bundled with the peer chain ID and snapshot freshness key.
|
|
830
|
+
/// @dev Lets aggregators (e.g. `JBSuckerRegistry`) read the value, the peer chain it belongs to, and its
|
|
831
|
+
/// freshness in one call instead of three separate staticcalls. The `value` is identical to
|
|
832
|
+
/// `peerChainSurplusOf`.
|
|
833
|
+
/// @param decimals The decimal precision for the returned value.
|
|
834
|
+
/// @param currency The currency to normalize to (e.g. `uint256(uint160(JBConstants.NATIVE_TOKEN))` for ETH).
|
|
835
|
+
/// @return A `JBPeerChainValue` with the converted surplus, peer chain ID, and snapshot freshness key.
|
|
836
|
+
function peerChainSurplusValueOf(
|
|
837
|
+
uint256 decimals,
|
|
838
|
+
uint256 currency
|
|
839
|
+
)
|
|
840
|
+
external
|
|
841
|
+
view
|
|
842
|
+
returns (JBPeerChainValue memory)
|
|
843
|
+
{
|
|
844
|
+
return JBPeerChainValue({
|
|
845
|
+
value: _convertPeerValue({source: _peerChainSurplus, decimals: decimals, currency: currency}),
|
|
846
|
+
peerChainId: peerChainId(),
|
|
847
|
+
snapshotTimestamp: snapshotTimestamp
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
/// @notice The peer chain total supply bundled with the peer chain ID and snapshot freshness key.
|
|
852
|
+
/// @dev Lets aggregators (e.g. `JBSuckerRegistry`) read the value, the peer chain it belongs to, and its
|
|
853
|
+
/// freshness in one call instead of three separate staticcalls. The `value` is identical to
|
|
854
|
+
/// `peerChainTotalSupply`.
|
|
855
|
+
/// @return A `JBPeerChainValue` with the total supply, peer chain ID, and snapshot freshness key.
|
|
856
|
+
function peerChainTotalSupplyValue() external view returns (JBPeerChainValue memory) {
|
|
857
|
+
return JBPeerChainValue({
|
|
858
|
+
value: peerChainTotalSupply, peerChainId: peerChainId(), snapshotTimestamp: snapshotTimestamp
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
|
|
810
862
|
/// @notice Information about the token on the remote chain that the given token on the local chain is mapped to.
|
|
811
863
|
/// @param token The local terminal token to get the remote token for.
|
|
812
864
|
/// @return The remote token mapping for the given local token.
|
|
@@ -841,6 +893,12 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
|
|
|
841
893
|
return amount;
|
|
842
894
|
}
|
|
843
895
|
|
|
896
|
+
/// @notice Returns the chain on which the peer is located.
|
|
897
|
+
/// @dev `public` (not `external`) so the combined peer-chain views in this contract can read it internally
|
|
898
|
+
/// without a self-call; subclasses implement the bridge-specific chain ID.
|
|
899
|
+
/// @return chain ID of the peer.
|
|
900
|
+
function peerChainId() public view virtual returns (uint256);
|
|
901
|
+
|
|
844
902
|
/// @notice The peer sucker on the remote chain, as a bytes32 for cross-VM compatibility.
|
|
845
903
|
/// @dev Defaults to `_toBytes32(address(this))`, assuming deterministic cross-chain deployment via CREATE2. The
|
|
846
904
|
/// deployer (`JBSuckerDeployer`) uses `salt = keccak256(abi.encodePacked(_msgSender(), salt))` to ensure
|
package/src/JBSuckerRegistry.sol
CHANGED
|
@@ -11,7 +11,7 @@ import {ERC2771Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol"
|
|
|
11
11
|
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
|
|
12
12
|
import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol";
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import {JBPeerChainValue} from "./structs/JBPeerChainValue.sol";
|
|
15
15
|
import {JBSuckerState} from "./enums/JBSuckerState.sol";
|
|
16
16
|
import {IJBSucker} from "./interfaces/IJBSucker.sol";
|
|
17
17
|
import {IJBSuckerDeployer} from "./interfaces/IJBSuckerDeployer.sol";
|
|
@@ -231,16 +231,12 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
|
|
|
231
231
|
(, uint256 val) = _suckersOf[projectId].tryGet(allSuckers[i]);
|
|
232
232
|
// Include both active and deprecated suckers in aggregate economic views.
|
|
233
233
|
if (val == _SUCKER_EXISTS || val == _SUCKER_DEPRECATED) {
|
|
234
|
-
|
|
235
|
-
|
|
234
|
+
// One call returns the value, peer chain ID, and snapshot freshness key together.
|
|
235
|
+
try IJBSucker(allSuckers[i]).peerChainBalanceValueOf({decimals: decimals, currency: currency}) returns (
|
|
236
|
+
JBPeerChainValue memory read
|
|
236
237
|
) {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
scratch: scratch,
|
|
240
|
-
chainId: chainId,
|
|
241
|
-
value: amt.value,
|
|
242
|
-
snapshotTimestamp: _snapshotTimestampOf(allSuckers[i]),
|
|
243
|
-
isActive: val == _SUCKER_EXISTS
|
|
238
|
+
scratch.chainCount = _recordPeerChainValue({
|
|
239
|
+
scratch: scratch, read: read, sucker: allSuckers[i], isActive: val == _SUCKER_EXISTS
|
|
244
240
|
});
|
|
245
241
|
} catch {}
|
|
246
242
|
}
|
|
@@ -287,16 +283,12 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
|
|
|
287
283
|
(, uint256 val) = _suckersOf[projectId].tryGet(allSuckers[i]);
|
|
288
284
|
// Include both active and deprecated suckers in aggregate economic views.
|
|
289
285
|
if (val == _SUCKER_EXISTS || val == _SUCKER_DEPRECATED) {
|
|
290
|
-
|
|
291
|
-
|
|
286
|
+
// One call returns the value, peer chain ID, and snapshot freshness key together.
|
|
287
|
+
try IJBSucker(allSuckers[i]).peerChainSurplusValueOf({decimals: decimals, currency: currency}) returns (
|
|
288
|
+
JBPeerChainValue memory read
|
|
292
289
|
) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
scratch: scratch,
|
|
296
|
-
chainId: chainId,
|
|
297
|
-
value: amt.value,
|
|
298
|
-
snapshotTimestamp: _snapshotTimestampOf(allSuckers[i]),
|
|
299
|
-
isActive: val == _SUCKER_EXISTS
|
|
290
|
+
scratch.chainCount = _recordPeerChainValue({
|
|
291
|
+
scratch: scratch, read: read, sucker: allSuckers[i], isActive: val == _SUCKER_EXISTS
|
|
300
292
|
});
|
|
301
293
|
} catch {}
|
|
302
294
|
}
|
|
@@ -332,14 +324,10 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
|
|
|
332
324
|
(, uint256 val) = _suckersOf[projectId].tryGet(allSuckers[i]);
|
|
333
325
|
// Include both active and deprecated suckers in aggregate economic views.
|
|
334
326
|
if (val == _SUCKER_EXISTS || val == _SUCKER_DEPRECATED) {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
scratch.chainCount =
|
|
338
|
-
scratch: scratch,
|
|
339
|
-
chainId: chainId,
|
|
340
|
-
value: supply,
|
|
341
|
-
snapshotTimestamp: _snapshotTimestampOf(allSuckers[i]),
|
|
342
|
-
isActive: val == _SUCKER_EXISTS
|
|
327
|
+
// One call returns the value, peer chain ID, and snapshot freshness key together.
|
|
328
|
+
try IJBSucker(allSuckers[i]).peerChainTotalSupplyValue() returns (JBPeerChainValue memory read) {
|
|
329
|
+
scratch.chainCount = _recordPeerChainValue({
|
|
330
|
+
scratch: scratch, read: read, sucker: allSuckers[i], isActive: val == _SUCKER_EXISTS
|
|
343
331
|
});
|
|
344
332
|
} catch {}
|
|
345
333
|
}
|
|
@@ -459,16 +447,34 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
|
|
|
459
447
|
}
|
|
460
448
|
}
|
|
461
449
|
|
|
462
|
-
/// @notice
|
|
463
|
-
/// @dev
|
|
464
|
-
///
|
|
465
|
-
///
|
|
466
|
-
///
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
450
|
+
/// @notice Records a combined peer-chain read (value, peer chain ID, snapshot freshness key) from one sucker.
|
|
451
|
+
/// @dev A wrapper over `_recordPeerValue` that unpacks the single-call `JBPeerChainValue` read and enforces the
|
|
452
|
+
/// same non-zero peer-chain requirement the registry applies everywhere else. The peer-chain check reverts here
|
|
453
|
+
/// (inside the caller's `try` success body, so the revert propagates) to preserve the prior behavior where a
|
|
454
|
+
/// sucker reporting a zero peer chain ID fails the whole aggregate view.
|
|
455
|
+
/// @param scratch The per-chain aggregate values and freshness keys recorded so far.
|
|
456
|
+
/// @param read The combined value, peer chain ID, and snapshot freshness key returned by the sucker.
|
|
457
|
+
/// @param sucker The sucker the read came from, used only for the zero-peer-chain error.
|
|
458
|
+
/// @param isActive Whether the value came from an active sucker.
|
|
459
|
+
/// @return The updated number of populated chain entries.
|
|
460
|
+
function _recordPeerChainValue(
|
|
461
|
+
PeerValueScratch memory scratch,
|
|
462
|
+
JBPeerChainValue memory read,
|
|
463
|
+
address sucker,
|
|
464
|
+
bool isActive
|
|
465
|
+
)
|
|
466
|
+
internal
|
|
467
|
+
pure
|
|
468
|
+
returns (uint256)
|
|
469
|
+
{
|
|
470
|
+
if (read.peerChainId == 0) revert JBSuckerRegistry_ZeroPeerChainId({sucker: sucker});
|
|
471
|
+
return _recordPeerValue({
|
|
472
|
+
scratch: scratch,
|
|
473
|
+
chainId: read.peerChainId,
|
|
474
|
+
value: read.value,
|
|
475
|
+
snapshotTimestamp: read.snapshotTimestamp,
|
|
476
|
+
isActive: isActive
|
|
477
|
+
});
|
|
472
478
|
}
|
|
473
479
|
|
|
474
480
|
//*********************************************************************//
|
|
@@ -9,6 +9,7 @@ import {JBClaim} from "../structs/JBClaim.sol";
|
|
|
9
9
|
import {JBDenominatedAmount} from "../structs/JBDenominatedAmount.sol";
|
|
10
10
|
import {JBInboxTreeRoot} from "../structs/JBInboxTreeRoot.sol";
|
|
11
11
|
import {JBOutboxTree} from "../structs/JBOutboxTree.sol";
|
|
12
|
+
import {JBPeerChainValue} from "../structs/JBPeerChainValue.sol";
|
|
12
13
|
import {JBRemoteToken} from "../structs/JBRemoteToken.sol";
|
|
13
14
|
import {JBSuckerState} from "../enums/JBSuckerState.sol";
|
|
14
15
|
import {JBTokenMapping} from "../structs/JBTokenMapping.sol";
|
|
@@ -160,6 +161,14 @@ interface IJBSucker is IERC165 {
|
|
|
160
161
|
/// @return A `JBDenominatedAmount` with the converted value.
|
|
161
162
|
function peerChainBalanceOf(uint256 decimals, uint256 currency) external view returns (JBDenominatedAmount memory);
|
|
162
163
|
|
|
164
|
+
/// @notice The peer chain balance bundled with the peer chain ID and snapshot freshness key.
|
|
165
|
+
/// @dev Lets aggregators read the value, the peer chain it belongs to, and its freshness in one call. The
|
|
166
|
+
/// `value` matches `peerChainBalanceOf`.
|
|
167
|
+
/// @param decimals The decimal precision for the returned value.
|
|
168
|
+
/// @param currency The currency to normalize to.
|
|
169
|
+
/// @return A `JBPeerChainValue` with the converted balance, peer chain ID, and snapshot freshness key.
|
|
170
|
+
function peerChainBalanceValueOf(uint256 decimals, uint256 currency) external view returns (JBPeerChainValue memory);
|
|
171
|
+
|
|
163
172
|
/// @notice The aggregate peer chain surplus, normalized to a desired currency and decimal precision using JBPrices.
|
|
164
173
|
/// @dev The surplus is stored as ETH-denominated (18 decimals) and converted to the requested currency/decimals
|
|
165
174
|
/// using the local JBPrices oracle.
|
|
@@ -168,12 +177,26 @@ interface IJBSucker is IERC165 {
|
|
|
168
177
|
/// @return A `JBDenominatedAmount` with the converted value.
|
|
169
178
|
function peerChainSurplusOf(uint256 decimals, uint256 currency) external view returns (JBDenominatedAmount memory);
|
|
170
179
|
|
|
180
|
+
/// @notice The peer chain surplus bundled with the peer chain ID and snapshot freshness key.
|
|
181
|
+
/// @dev Lets aggregators read the value, the peer chain it belongs to, and its freshness in one call. The
|
|
182
|
+
/// `value` matches `peerChainSurplusOf`.
|
|
183
|
+
/// @param decimals The decimal precision for the returned value.
|
|
184
|
+
/// @param currency The currency to normalize to.
|
|
185
|
+
/// @return A `JBPeerChainValue` with the converted surplus, peer chain ID, and snapshot freshness key.
|
|
186
|
+
function peerChainSurplusValueOf(uint256 decimals, uint256 currency) external view returns (JBPeerChainValue memory);
|
|
187
|
+
|
|
171
188
|
/// @notice The last known total token supply on the peer chain, updated each time a bridge message is received.
|
|
172
189
|
/// @dev Used by data hooks to compute `effectiveTotalSupply = localSupply + sum(peerChainTotalSupply)` across all
|
|
173
190
|
/// suckers, preventing cash out tax bypass on chains where a holder dominates the local supply.
|
|
174
191
|
/// @return The peer chain's total supply.
|
|
175
192
|
function peerChainTotalSupply() external view returns (uint256);
|
|
176
193
|
|
|
194
|
+
/// @notice The peer chain total supply bundled with the peer chain ID and snapshot freshness key.
|
|
195
|
+
/// @dev Lets aggregators read the value, the peer chain it belongs to, and its freshness in one call. The
|
|
196
|
+
/// `value` matches `peerChainTotalSupply`.
|
|
197
|
+
/// @return A `JBPeerChainValue` with the total supply, peer chain ID, and snapshot freshness key.
|
|
198
|
+
function peerChainTotalSupplyValue() external view returns (JBPeerChainValue memory);
|
|
199
|
+
|
|
177
200
|
/// @notice The ID of the project on the local chain that this sucker is associated with.
|
|
178
201
|
/// @return The project ID.
|
|
179
202
|
function projectId() external view returns (uint256);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
/// @notice A single peer-chain aggregate read bundled with the keys the registry needs to dedupe and rank it.
|
|
5
|
+
/// @dev Returned by the sucker's combined peer-chain views so the registry can read the value, the peer chain it
|
|
6
|
+
/// belongs to, and its snapshot freshness in one call instead of three separate staticcalls.
|
|
7
|
+
/// @custom:member value The requested peer-chain amount (balance, surplus, or total supply), already converted to the
|
|
8
|
+
/// caller's currency and decimals where applicable.
|
|
9
|
+
/// @custom:member peerChainId The chain ID of the remote peer this snapshot describes.
|
|
10
|
+
/// @custom:member snapshotTimestamp The freshness key of the snapshot the value came from.
|
|
11
|
+
struct JBPeerChainValue {
|
|
12
|
+
uint256 value;
|
|
13
|
+
uint256 peerChainId;
|
|
14
|
+
uint256 snapshotTimestamp;
|
|
15
|
+
}
|