@bananapus/suckers-v6 0.0.72 → 0.0.73
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/README.md +1 -1
- package/package.json +9 -8
- package/src/JBSucker.sol +9 -15
- package/src/JBSuckerRegistry.sol +2 -4
- package/src/interfaces/IJBSucker.sol +1 -2
- package/src/interfaces/IJBSuckerRegistry.sol +1 -2
- package/src/libraries/JBSuckerLib.sol +5 -8
- package/src/structs/JBInboxTreeRoot.sol +1 -2
- package/src/archive/IJBCeloSuckerDeployer.sol +0 -25
- package/src/archive/IJBSwapCCIPSuckerDeployer.sol +0 -28
- package/src/archive/JBCeloSucker.sol +0 -188
- package/src/archive/JBCeloSuckerDeployer.sol +0 -96
- package/src/archive/JBConversionRate.sol +0 -12
- package/src/archive/JBPendingSwap.sol +0 -12
- package/src/archive/JBSwapCCIPSucker.sol +0 -756
- package/src/archive/JBSwapCCIPSuckerDeployer.sol +0 -118
- package/src/archive/JBSwapLib.sol +0 -148
- package/src/archive/JBSwapPoolLib.sol +0 -1142
- package/src/archive/README.md +0 -5
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
- [AUDIT_INSTRUCTIONS.md](./AUDIT_INSTRUCTIONS.md) — scope, entrypoints, and reading order for security review.
|
|
14
14
|
- [SKILLS.md](./SKILLS.md) — reusable patterns and gotchas distilled from this codebase.
|
|
15
15
|
- [STYLE_GUIDE.md](./STYLE_GUIDE.md) — Solidity conventions used across this repo.
|
|
16
|
-
- [CHANGELOG.md](./CHANGELOG.md)
|
|
16
|
+
- [CHANGELOG.md](./CHANGELOG.md) - V5 to V6 migration changelog.
|
|
17
17
|
|
|
18
18
|
The codebase includes multiple bridge variants, but the canonical deployment and discovery tooling in this repo is narrower than the full runtime surface. Treat the deployment scripts and helper libraries as the source of truth for what is operationally supported today.
|
|
19
19
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bananapus/suckers-v6",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.73",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"references/",
|
|
12
12
|
"remappings.txt",
|
|
13
13
|
"script/",
|
|
14
|
-
"src/"
|
|
14
|
+
"src/",
|
|
15
|
+
"!src/archive/"
|
|
15
16
|
],
|
|
16
17
|
"engines": {
|
|
17
18
|
"node": ">=20.0.0"
|
|
@@ -26,18 +27,18 @@
|
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
28
29
|
"@arbitrum/nitro-contracts": "3.2.0",
|
|
29
|
-
"@bananapus/core-v6": "^0.0.
|
|
30
|
-
"@bananapus/permission-ids-v6": "^0.0.
|
|
30
|
+
"@bananapus/core-v6": "^0.0.82",
|
|
31
|
+
"@bananapus/permission-ids-v6": "^0.0.30",
|
|
31
32
|
"@chainlink/contracts-ccip": "1.6.4",
|
|
32
|
-
"@chainlink/local": "0.2.7",
|
|
33
33
|
"@openzeppelin/contracts": "5.6.1",
|
|
34
|
-
"@prb/math": "4.1.
|
|
35
|
-
"@uniswap/v3-core": "github:Uniswap/v3-core#6562c52e8f75f0c10f9deaf44861847585fc8129",
|
|
36
|
-
"@uniswap/v3-periphery": "github:Uniswap/v3-periphery#b325bb0905d922ae61fcc7df85ee802e8df5e96c",
|
|
34
|
+
"@prb/math": "4.1.2",
|
|
37
35
|
"@uniswap/v4-core": "1.0.2",
|
|
38
36
|
"solady": "0.1.26"
|
|
39
37
|
},
|
|
40
38
|
"devDependencies": {
|
|
39
|
+
"@chainlink/local": "0.2.9",
|
|
40
|
+
"@uniswap/v3-core": "1.0.1",
|
|
41
|
+
"@uniswap/v3-periphery": "1.4.4",
|
|
41
42
|
"@sphinx-labs/plugins": "0.33.3"
|
|
42
43
|
}
|
|
43
44
|
}
|
package/src/JBSucker.sol
CHANGED
|
@@ -311,10 +311,9 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
|
|
|
311
311
|
/// @dev A zero value preserves the default same-address deterministic peer.
|
|
312
312
|
bytes32 private _peer;
|
|
313
313
|
|
|
314
|
-
/// @notice The peer chain's per-currency surplus and balance from the latest snapshot.
|
|
315
|
-
///
|
|
316
|
-
///
|
|
317
|
-
/// versioning or clearing is needed. A read sums these and values them into the requested currency.
|
|
314
|
+
/// @notice The peer chain's per-currency surplus and balance from the latest snapshot.
|
|
315
|
+
/// @dev Rebuilt from each fresher snapshot; dropped contexts are absent without per-entry versioning or clearing.
|
|
316
|
+
/// A read sums these and values them into the requested currency.
|
|
318
317
|
JBPeerChainContext[] private _peerContexts;
|
|
319
318
|
|
|
320
319
|
//*********************************************************************//
|
|
@@ -645,8 +644,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
|
|
|
645
644
|
|
|
646
645
|
/// @notice Configure which remote-chain tokens each local terminal token maps to, enabling (or disabling) those
|
|
647
646
|
/// tokens for cross-chain bridging. Setting a remote token to `bytes32(0)` disables bridging and flushes any
|
|
648
|
-
/// pending outbox entries. Requires `MAP_SUCKER_TOKEN` permission from the project owner
|
|
649
|
-
/// registry during deployment).
|
|
647
|
+
/// pending outbox entries. Requires `MAP_SUCKER_TOKEN` permission from the project owner or deployment registry.
|
|
650
648
|
/// @param maps A list of local and remote terminal token addresses to map, and minimum amount/gas limits for
|
|
651
649
|
/// bridging them.
|
|
652
650
|
function mapTokens(JBTokenMapping[] calldata maps) external payable override {
|
|
@@ -705,8 +703,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
|
|
|
705
703
|
/// For EVM peers: the EVM address left-padded to 32 bytes via `_toBytes32`.
|
|
706
704
|
/// For SVM peers: the full 32-byte Solana public key.
|
|
707
705
|
/// @param minTokensReclaimed The minimum amount of terminal tokens to cash out for. If the amount cashed out is
|
|
708
|
-
/// less
|
|
709
|
-
/// than this, the transaction will revert.
|
|
706
|
+
/// less than this, the transaction will revert.
|
|
710
707
|
/// @param token The address of the terminal token to cash out for.
|
|
711
708
|
function prepare(
|
|
712
709
|
uint256 projectTokenCount,
|
|
@@ -904,9 +901,8 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
|
|
|
904
901
|
}
|
|
905
902
|
|
|
906
903
|
/// @notice The peer chain total supply bundled with the peer chain ID and snapshot freshness key.
|
|
907
|
-
/// @dev Lets aggregators (e.g. `JBSuckerRegistry`) read the value,
|
|
908
|
-
///
|
|
909
|
-
/// `peerChainTotalSupply`.
|
|
904
|
+
/// @dev Lets aggregators (e.g. `JBSuckerRegistry`) read the value, peer chain, and freshness in one call instead
|
|
905
|
+
/// of three separate staticcalls. The `value` is identical to `peerChainTotalSupply`.
|
|
910
906
|
/// @return A `JBPeerChainValue` with the total supply, peer chain ID, and snapshot freshness key.
|
|
911
907
|
function peerChainTotalSupplyValue() external view returns (JBPeerChainValue memory) {
|
|
912
908
|
return JBPeerChainValue({
|
|
@@ -1074,8 +1070,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
|
|
|
1074
1070
|
deployer = _msgSender();
|
|
1075
1071
|
}
|
|
1076
1072
|
|
|
1077
|
-
/// @notice Map an ERC-20 token on the local chain to
|
|
1078
|
-
/// bridged.
|
|
1073
|
+
/// @notice Map an ERC-20 token on the local chain to a remote-chain ERC-20 token for bridging.
|
|
1079
1074
|
/// @param map The local and remote terminal token addresses to map, and minimum amount/gas limits for bridging
|
|
1080
1075
|
/// them.
|
|
1081
1076
|
function mapToken(JBTokenMapping calldata map) public payable override {
|
|
@@ -1220,8 +1215,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
|
|
|
1220
1215
|
/// @return valid Whether the sender is the remote peer.
|
|
1221
1216
|
function _isRemotePeer(address sender) internal virtual returns (bool valid);
|
|
1222
1217
|
|
|
1223
|
-
/// @notice Map an ERC-20 token on the local chain to
|
|
1224
|
-
/// bridged or disabled.
|
|
1218
|
+
/// @notice Map an ERC-20 token on the local chain to a remote-chain ERC-20 token, or disable bridging.
|
|
1225
1219
|
/// @dev Once a token has outbox tree entries (`_outboxOf[token].tree.count != 0`), it cannot be remapped to a
|
|
1226
1220
|
/// different remote token -- it can only be disabled by mapping to `address(0)`, which triggers a final root
|
|
1227
1221
|
/// flush to settle outstanding claims. This permanence prevents double-spending: if a remapping were allowed
|
package/src/JBSuckerRegistry.sol
CHANGED
|
@@ -156,8 +156,7 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
|
|
|
156
156
|
return exists && (val == _SUCKER_EXISTS || val == _SUCKER_DEPRECATED);
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
/// @notice Values one sucker's raw peer-chain balance into a currency
|
|
160
|
-
/// freshness.
|
|
159
|
+
/// @notice Values one sucker's raw peer-chain balance into a currency with peer chain ID and freshness.
|
|
161
160
|
/// @dev Exposed as an external self-call boundary so `totalRemoteBalanceOf` can `try` it and drop a single sucker
|
|
162
161
|
/// whose price feed is missing. A context whose currency already matches `currency` folds in at par (no feed read);
|
|
163
162
|
/// a missing cross-currency feed reverts, and the aggregator catches it and skips just this sucker.
|
|
@@ -206,8 +205,7 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
|
|
|
206
205
|
return JBPeerChainValue({value: value, peerChainId: chainId, snapshotTimestamp: snapshot});
|
|
207
206
|
}
|
|
208
207
|
|
|
209
|
-
/// @notice Values one sucker's raw peer-chain surplus into a currency
|
|
210
|
-
/// freshness.
|
|
208
|
+
/// @notice Values one sucker's raw peer-chain surplus into a currency with peer chain ID and freshness.
|
|
211
209
|
/// @dev Exposed as an external self-call boundary so `totalRemoteSurplusOf` can `try` it and drop a single sucker
|
|
212
210
|
/// whose price feed is missing. A context whose currency already matches `currency` folds in at par (no feed read);
|
|
213
211
|
/// a missing cross-currency feed reverts, and the aggregator catches it and skips just this sucker.
|
|
@@ -222,8 +222,7 @@ interface IJBSucker is IERC165 {
|
|
|
222
222
|
/// @param token The terminal token to cash out into.
|
|
223
223
|
/// @param metadata Opaque caller-defined attribution payload included in the leaf hash. The sucker protocol does
|
|
224
224
|
/// not inspect this value — it's covered by the merkle root, so the destination contract that consumes the claim
|
|
225
|
-
/// can
|
|
226
|
-
/// trust it once the proof verifies. Pass `bytes32(0)` for an ordinary bridge with no attribution context.
|
|
225
|
+
/// can trust it once the proof verifies. Pass `bytes32(0)` for an ordinary bridge with no attribution context.
|
|
227
226
|
function prepare(
|
|
228
227
|
uint256 projectTokenCount,
|
|
229
228
|
bytes32 beneficiary,
|
|
@@ -62,8 +62,7 @@ interface IJBSuckerRegistry {
|
|
|
62
62
|
/// @return The addresses of every sucker ever registered for `projectId`.
|
|
63
63
|
function allSuckersOf(uint256 projectId) external view returns (address[] memory);
|
|
64
64
|
|
|
65
|
-
/// @notice Returns true if the specified sucker belongs to the
|
|
66
|
-
/// registry.
|
|
65
|
+
/// @notice Returns true if the specified sucker belongs to the project and was deployed through this registry.
|
|
67
66
|
/// @param projectId The ID of the project to check for.
|
|
68
67
|
/// @param addr The address of the sucker to check.
|
|
69
68
|
/// @return Whether the sucker belongs to the project.
|
|
@@ -37,9 +37,7 @@ library JBSuckerLib {
|
|
|
37
37
|
|
|
38
38
|
/// @notice Build the cross-chain snapshot message (total supply plus per-context surplus and balance).
|
|
39
39
|
/// @dev Extracted from `JBSucker._buildSnapshotAndSend` to reduce child contract bytecode. Called via DELEGATECALL.
|
|
40
|
-
/// The snapshot
|
|
41
|
-
/// own
|
|
42
|
-
/// currency.
|
|
40
|
+
/// The snapshot carries each context's surplus and balance in its own currency, without price-feed valuation.
|
|
43
41
|
/// @param directory The JB directory to look up controllers and terminals.
|
|
44
42
|
/// @param projectId The project ID.
|
|
45
43
|
/// @param remoteToken The remote token bytes32 address.
|
|
@@ -311,11 +309,10 @@ library JBSuckerLib {
|
|
|
311
309
|
}
|
|
312
310
|
|
|
313
311
|
/// @notice Builds the local accounting values used in outbound peer-chain snapshots.
|
|
314
|
-
/// @dev Project token supply stays a single currency-agnostic scalar. Surplus and balance are emitted per
|
|
315
|
-
///
|
|
316
|
-
///
|
|
317
|
-
///
|
|
318
|
-
/// own per-context surplus/balance, appended to the terminal contexts.
|
|
312
|
+
/// @dev Project token supply stays a single currency-agnostic scalar. Surplus and balance are emitted per context
|
|
313
|
+
/// in that context's currency, with no price-feed valuation. The receiving chain folds each context into its
|
|
314
|
+
/// same-asset local context at par. A project data hook may contribute additional supply plus its own per-context
|
|
315
|
+
/// surplus/balance, appended to the terminal contexts.
|
|
319
316
|
/// @param directory The JB directory to look up controllers and terminals.
|
|
320
317
|
/// @param projectId The project to snapshot.
|
|
321
318
|
/// @return localTotalSupply The total project token supply, including reserved tokens.
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
pragma solidity ^0.8.0;
|
|
3
3
|
|
|
4
4
|
/// @notice The root of an inbox tree for a given token in a `JBSucker`.
|
|
5
|
-
/// @dev Inbox trees are used to receive from the remote chain to the local chain. Tokens can be
|
|
6
|
-
/// inbox tree.
|
|
5
|
+
/// @dev Inbox trees are used to receive from the remote chain to the local chain. Tokens can be claimed from the tree.
|
|
7
6
|
/// @custom:member nonce Tracks the nonce of the tree. The nonce cannot decrease.
|
|
8
7
|
/// @custom:member root The root of the tree.
|
|
9
8
|
struct JBInboxTreeRoot {
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.0;
|
|
3
|
-
|
|
4
|
-
import {IJBOpSuckerDeployer} from "./IJBOpSuckerDeployer.sol";
|
|
5
|
-
import {IWrappedNativeToken} from "./IWrappedNativeToken.sol";
|
|
6
|
-
import {IOPMessenger} from "./IOPMessenger.sol";
|
|
7
|
-
import {IOPStandardBridge} from "./IOPStandardBridge.sol";
|
|
8
|
-
|
|
9
|
-
/// @notice Interface for a deployer of Celo-specific suckers (OP Stack with custom gas token).
|
|
10
|
-
interface IJBCeloSuckerDeployer is IJBOpSuckerDeployer {
|
|
11
|
-
// View functions
|
|
12
|
-
|
|
13
|
-
/// @notice The ERC-20 wrapper for the chain's native token on the local chain.
|
|
14
|
-
function wrappedNative() external view returns (IWrappedNativeToken);
|
|
15
|
-
|
|
16
|
-
// State-changing functions
|
|
17
|
-
|
|
18
|
-
/// @notice Set the chain-specific OP messenger, bridge, and wrapped native token constants.
|
|
19
|
-
function setChainSpecificConstants(
|
|
20
|
-
IOPMessenger messenger,
|
|
21
|
-
IOPStandardBridge bridge,
|
|
22
|
-
IWrappedNativeToken wrappedNative
|
|
23
|
-
)
|
|
24
|
-
external;
|
|
25
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.0;
|
|
3
|
-
|
|
4
|
-
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
5
|
-
import {IUniswapV3Factory} from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol";
|
|
6
|
-
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
|
|
7
|
-
|
|
8
|
-
import {IJBCCIPSuckerDeployer} from "./IJBCCIPSuckerDeployer.sol";
|
|
9
|
-
|
|
10
|
-
/// @notice Interface for a deployer of swap-enabled CCIP suckers.
|
|
11
|
-
/// @dev Extends the base CCIP deployer with Uniswap V3/V4 swap configuration for cross-currency bridging.
|
|
12
|
-
interface IJBSwapCCIPSuckerDeployer is IJBCCIPSuckerDeployer {
|
|
13
|
-
/// @notice The ERC-20 token used for CCIP bridging (e.g., USDC — exists on both chains).
|
|
14
|
-
function bridgeToken() external view returns (IERC20);
|
|
15
|
-
|
|
16
|
-
/// @notice The Uniswap V4 PoolManager. Can be address(0) if V4 is unavailable on this chain.
|
|
17
|
-
function poolManager() external view returns (IPoolManager);
|
|
18
|
-
|
|
19
|
-
/// @notice The Uniswap V3 factory. Can be address(0) if V3 is unavailable on this chain.
|
|
20
|
-
function v3Factory() external view returns (IUniswapV3Factory);
|
|
21
|
-
|
|
22
|
-
/// @notice The Uniswap V4 hook address used during pool discovery (optional).
|
|
23
|
-
function univ4Hook() external view returns (address);
|
|
24
|
-
|
|
25
|
-
/// @notice The ERC-20 wrapper address for the chain's native token (e.g. WETH on Ethereum). Used for V3 native
|
|
26
|
-
/// swaps.
|
|
27
|
-
function wrappedNativeToken() external view returns (address);
|
|
28
|
-
}
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity 0.8.28;
|
|
3
|
-
|
|
4
|
-
import {IJBDirectory} from "@bananapus/core-v6/src/interfaces/IJBDirectory.sol";
|
|
5
|
-
import {IJBPermissions} from "@bananapus/core-v6/src/interfaces/IJBPermissions.sol";
|
|
6
|
-
import {IJBTerminal} from "@bananapus/core-v6/src/interfaces/IJBTerminal.sol";
|
|
7
|
-
import {IJBTokens} from "@bananapus/core-v6/src/interfaces/IJBTokens.sol";
|
|
8
|
-
import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
|
|
9
|
-
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
10
|
-
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
11
|
-
|
|
12
|
-
import {JBSucker} from "./JBSucker.sol";
|
|
13
|
-
import {JBOptimismSucker} from "./JBOptimismSucker.sol";
|
|
14
|
-
import {JBCeloSuckerDeployer} from "./deployers/JBCeloSuckerDeployer.sol";
|
|
15
|
-
import {IJBSuckerRegistry} from "./interfaces/IJBSuckerRegistry.sol";
|
|
16
|
-
import {IWrappedNativeToken} from "./interfaces/IWrappedNativeToken.sol";
|
|
17
|
-
import {JBMessageRoot} from "./structs/JBMessageRoot.sol";
|
|
18
|
-
import {JBRemoteToken} from "./structs/JBRemoteToken.sol";
|
|
19
|
-
import {JBTokenMapping} from "./structs/JBTokenMapping.sol";
|
|
20
|
-
|
|
21
|
-
/// @notice A `JBSucker` implementation for Celo — an OP Stack chain with a custom gas token (CELO, not ETH).
|
|
22
|
-
/// @dev ETH exists on Celo only as an ERC-20. This sucker wraps native ETH before bridging
|
|
23
|
-
/// as ERC-20 via the OP standard bridge, and removes the `NATIVE_TOKEN → NATIVE_TOKEN` restriction so that
|
|
24
|
-
/// native ETH can map to a remote ERC-20.
|
|
25
|
-
contract JBCeloSucker is JBOptimismSucker {
|
|
26
|
-
//*********************************************************************//
|
|
27
|
-
// --------------- public immutable stored properties ---------------- //
|
|
28
|
-
//*********************************************************************//
|
|
29
|
-
|
|
30
|
-
/// @notice The ERC-20 wrapper for the chain's native token on the local chain.
|
|
31
|
-
IWrappedNativeToken public immutable WRAPPED_NATIVE_TOKEN;
|
|
32
|
-
|
|
33
|
-
//*********************************************************************//
|
|
34
|
-
// ---------------------------- constructor -------------------------- //
|
|
35
|
-
//*********************************************************************//
|
|
36
|
-
|
|
37
|
-
/// @param deployer A contract that deploys clones of this contract.
|
|
38
|
-
/// @param directory A contract storing directories of terminals and controllers for each project.
|
|
39
|
-
/// @param permissions A contract storing permissions.
|
|
40
|
-
/// @param tokens A contract that manages token minting and burning.
|
|
41
|
-
constructor(
|
|
42
|
-
JBCeloSuckerDeployer deployer,
|
|
43
|
-
IJBDirectory directory,
|
|
44
|
-
IJBPermissions permissions,
|
|
45
|
-
IJBTokens tokens,
|
|
46
|
-
uint256 feeProjectId,
|
|
47
|
-
IJBSuckerRegistry registry,
|
|
48
|
-
address trustedForwarder
|
|
49
|
-
)
|
|
50
|
-
JBOptimismSucker(deployer, directory, permissions, tokens, feeProjectId, registry, trustedForwarder)
|
|
51
|
-
{
|
|
52
|
-
// Fetch the wrapped native token by doing a callback to the deployer contract.
|
|
53
|
-
WRAPPED_NATIVE_TOKEN = JBCeloSuckerDeployer(deployer).wrappedNative();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
//*********************************************************************//
|
|
57
|
-
// ------------------------ external views --------------------------- //
|
|
58
|
-
//*********************************************************************//
|
|
59
|
-
|
|
60
|
-
/// @notice Returns the chain on which the peer is located.
|
|
61
|
-
/// @return chainId of the peer.
|
|
62
|
-
function peerChainId() external view virtual override returns (uint256) {
|
|
63
|
-
uint256 chainId = block.chainid;
|
|
64
|
-
if (chainId == 1) return 42_220;
|
|
65
|
-
if (chainId == 42_220) return 1;
|
|
66
|
-
return 0;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
//*********************************************************************//
|
|
70
|
-
// --------------------- internal transactions ----------------------- //
|
|
71
|
-
//*********************************************************************//
|
|
72
|
-
|
|
73
|
-
/// @notice Unwraps wrapped native tokens before adding to the project's balance.
|
|
74
|
-
/// @dev When tokens are bridged from Celo → L1 via the OP bridge, wrapped native tokens (ERC-20) are released to
|
|
75
|
-
/// the sucker. But the L1 project's terminal accepts native ETH (NATIVE_TOKEN), not the wrapped form. This override
|
|
76
|
-
/// unwraps
|
|
77
|
-
/// and adds native ETH to the project's balance.
|
|
78
|
-
/// @param token The terminal token to add to the project's balance.
|
|
79
|
-
/// @param amount The amount of terminal tokens to add to the project's balance.
|
|
80
|
-
/// @param cachedProjectId The cached project ID to avoid redundant storage reads.
|
|
81
|
-
function _addToBalance(address token, uint256 amount, uint256 cachedProjectId) internal override {
|
|
82
|
-
if (token == address(WRAPPED_NATIVE_TOKEN)) {
|
|
83
|
-
// Check addable amount against wrapped native token balance before unwrapping.
|
|
84
|
-
uint256 addableAmount = amountToAddToBalanceOf(token);
|
|
85
|
-
if (amount > addableAmount) {
|
|
86
|
-
revert JBSucker_InsufficientBalance({amount: amount, balance: addableAmount});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Unwrap wrapped native tokens → native tokens.
|
|
90
|
-
WRAPPED_NATIVE_TOKEN.withdraw(amount);
|
|
91
|
-
|
|
92
|
-
// Get the project's primary terminal for native token.
|
|
93
|
-
IJBTerminal terminal =
|
|
94
|
-
DIRECTORY.primaryTerminalOf({projectId: cachedProjectId, token: JBConstants.NATIVE_TOKEN});
|
|
95
|
-
|
|
96
|
-
if (address(terminal) == address(0)) {
|
|
97
|
-
revert JBSucker_NoTerminalForToken({projectId: cachedProjectId, token: JBConstants.NATIVE_TOKEN});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Add native ETH to the project's balance.
|
|
101
|
-
terminal.addToBalanceOf{value: amount}({
|
|
102
|
-
projectId: cachedProjectId,
|
|
103
|
-
token: JBConstants.NATIVE_TOKEN,
|
|
104
|
-
amount: amount,
|
|
105
|
-
shouldReturnHeldFees: false,
|
|
106
|
-
memo: "",
|
|
107
|
-
metadata: ""
|
|
108
|
-
});
|
|
109
|
-
} else {
|
|
110
|
-
super._addToBalance({token: token, amount: amount, cachedProjectId: cachedProjectId});
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/// @notice Use the `OPMESSENGER` to send the outbox tree for the `token` and the corresponding funds to the peer
|
|
115
|
-
/// over the `OPBRIDGE`.
|
|
116
|
-
/// @dev For Celo, native ETH is wrapped and bridged as ERC-20. The messenger message is sent with
|
|
117
|
-
/// `nativeValue = 0` because Celo's native token is CELO (not ETH), so we never attach ETH as msg.value.
|
|
118
|
-
/// @param transportPayment the amount of `msg.value` that is going to get paid for sending this message.
|
|
119
|
-
/// @param token The token to bridge the outbox tree for.
|
|
120
|
-
/// @param remoteToken Information about the remote token to bridge to.
|
|
121
|
-
// forge-lint: disable-next-line(mixed-case-function)
|
|
122
|
-
function _sendRootOverAMB(
|
|
123
|
-
uint256 transportPayment,
|
|
124
|
-
uint256 index,
|
|
125
|
-
address token,
|
|
126
|
-
uint256 amount,
|
|
127
|
-
JBRemoteToken memory remoteToken,
|
|
128
|
-
JBMessageRoot memory message
|
|
129
|
-
)
|
|
130
|
-
internal
|
|
131
|
-
override
|
|
132
|
-
{
|
|
133
|
-
index; // Silence unused parameter warning (not needed for Celo bridge).
|
|
134
|
-
|
|
135
|
-
// Revert if there's a `msg.value`. The Celo bridge does not expect to be paid.
|
|
136
|
-
if (transportPayment != 0) {
|
|
137
|
-
revert JBSucker_UnexpectedMsgValue({value: transportPayment});
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Cache peer address to avoid redundant calls.
|
|
141
|
-
address peerAddress = _toAddress(peer());
|
|
142
|
-
|
|
143
|
-
if (amount != 0) {
|
|
144
|
-
// Determine the local token to bridge — native ETH is wrapped first.
|
|
145
|
-
address bridgeToken = token;
|
|
146
|
-
if (token == JBConstants.NATIVE_TOKEN) {
|
|
147
|
-
// Wrap native tokens so they can be bridged as ERC-20.
|
|
148
|
-
WRAPPED_NATIVE_TOKEN.deposit{value: amount}();
|
|
149
|
-
bridgeToken = address(WRAPPED_NATIVE_TOKEN);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Approve the bridge to spend the token.
|
|
153
|
-
SafeERC20.forceApprove({token: IERC20(bridgeToken), spender: address(OPBRIDGE), value: amount});
|
|
154
|
-
|
|
155
|
-
// Bridge the ERC-20 token to the peer.
|
|
156
|
-
OPBRIDGE.bridgeERC20To({
|
|
157
|
-
localToken: bridgeToken,
|
|
158
|
-
remoteToken: _toAddress(remoteToken.addr),
|
|
159
|
-
to: peerAddress,
|
|
160
|
-
amount: amount,
|
|
161
|
-
minGasLimit: remoteToken.minGas,
|
|
162
|
-
extraData: bytes("")
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
SafeERC20.forceApprove({token: IERC20(bridgeToken), spender: address(OPBRIDGE), value: 0});
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Send the messenger message with nativeValue = 0.
|
|
169
|
-
// Celo's native token is CELO, not ETH — we never attach ETH as msg.value on the messenger.
|
|
170
|
-
// On L1, the ETH was already wrapped and bridged as ERC-20 above.
|
|
171
|
-
OPMESSENGER.sendMessage({
|
|
172
|
-
target: peerAddress,
|
|
173
|
-
message: abi.encodeCall(JBSucker.fromRemote, (message)),
|
|
174
|
-
gasLimit: MESSENGER_BASE_GAS_LIMIT
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/// @notice Allow `NATIVE_TOKEN` to map to any remote token (not just `NATIVE_TOKEN`).
|
|
179
|
-
/// @dev Celo uses CELO as native gas token. ETH is an ERC-20 on Celo. So `NATIVE_TOKEN` on L1
|
|
180
|
-
/// maps to an ERC-20 address on Celo, not to `NATIVE_TOKEN`. The base class restriction is removed.
|
|
181
|
-
function _validateTokenMapping(JBTokenMapping calldata map) internal pure virtual override {
|
|
182
|
-
// Enforce a reasonable minimum gas limit for bridging. Since we always bridge as ERC-20
|
|
183
|
-
// (wrapping native tokens), all tokens need sufficient gas for an ERC-20 transfer.
|
|
184
|
-
if (map.minGas < MESSENGER_ERC20_MIN_GAS_LIMIT) {
|
|
185
|
-
revert JBSucker_BelowMinGas({minGas: map.minGas, minGasLimit: MESSENGER_ERC20_MIN_GAS_LIMIT});
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity 0.8.28;
|
|
3
|
-
|
|
4
|
-
// External packages (alphabetized).
|
|
5
|
-
import {IJBDirectory} from "@bananapus/core-v6/src/interfaces/IJBDirectory.sol";
|
|
6
|
-
import {IJBPermissions} from "@bananapus/core-v6/src/interfaces/IJBPermissions.sol";
|
|
7
|
-
import {IJBTokens} from "@bananapus/core-v6/src/interfaces/IJBTokens.sol";
|
|
8
|
-
|
|
9
|
-
// Local: interfaces (alphabetized).
|
|
10
|
-
import {IJBCeloSuckerDeployer} from "../interfaces/IJBCeloSuckerDeployer.sol";
|
|
11
|
-
import {IOPMessenger} from "../interfaces/IOPMessenger.sol";
|
|
12
|
-
import {IOPStandardBridge} from "../interfaces/IOPStandardBridge.sol";
|
|
13
|
-
import {IWrappedNativeToken} from "../interfaces/IWrappedNativeToken.sol";
|
|
14
|
-
|
|
15
|
-
// Local: deployers.
|
|
16
|
-
import {JBOptimismSuckerDeployer} from "./JBOptimismSuckerDeployer.sol";
|
|
17
|
-
|
|
18
|
-
/// @notice An `IJBSuckerDeployer` implementation to deploy `JBCeloSucker` contracts.
|
|
19
|
-
/// @dev Extends the OP deployer with a `wrappedNative` address for chains where ETH is an ERC-20.
|
|
20
|
-
contract JBCeloSuckerDeployer is JBOptimismSuckerDeployer, IJBCeloSuckerDeployer {
|
|
21
|
-
//*********************************************************************//
|
|
22
|
-
// ---------------------- public stored properties ------------------- //
|
|
23
|
-
//*********************************************************************//
|
|
24
|
-
|
|
25
|
-
/// @notice The ERC-20 wrapper for the chain's native token on the local chain.
|
|
26
|
-
IWrappedNativeToken public override wrappedNative;
|
|
27
|
-
|
|
28
|
-
//*********************************************************************//
|
|
29
|
-
// ---------------------------- constructor -------------------------- //
|
|
30
|
-
//*********************************************************************//
|
|
31
|
-
|
|
32
|
-
/// @param directory The directory of terminals and controllers for projects.
|
|
33
|
-
/// @param permissions The permissions contract for the deployer.
|
|
34
|
-
/// @param tokens The contract that manages token minting and burning.
|
|
35
|
-
/// @param configurator The address of the configurator.
|
|
36
|
-
/// @param trustedForwarder The trusted forwarder for ERC-2771 meta-transactions.
|
|
37
|
-
constructor(
|
|
38
|
-
IJBDirectory directory,
|
|
39
|
-
IJBPermissions permissions,
|
|
40
|
-
IJBTokens tokens,
|
|
41
|
-
address configurator,
|
|
42
|
-
address trustedForwarder
|
|
43
|
-
)
|
|
44
|
-
JBOptimismSuckerDeployer(directory, permissions, tokens, configurator, trustedForwarder)
|
|
45
|
-
{}
|
|
46
|
-
|
|
47
|
-
//*********************************************************************//
|
|
48
|
-
// ------------------------ internal views --------------------------- //
|
|
49
|
-
//*********************************************************************//
|
|
50
|
-
|
|
51
|
-
/// @notice Check if the layer specific configuration is set or not. Used as a sanity check.
|
|
52
|
-
/// @return A flag indicating whether the layer specific configuration has been set.
|
|
53
|
-
function _layerSpecificConfigurationIsSet() internal view override returns (bool) {
|
|
54
|
-
return
|
|
55
|
-
address(opMessenger) != address(0) && address(opBridge) != address(0)
|
|
56
|
-
&& address(wrappedNative) != address(0);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
//*********************************************************************//
|
|
60
|
-
// --------------------- external transactions ----------------------- //
|
|
61
|
-
//*********************************************************************//
|
|
62
|
-
|
|
63
|
-
/// @notice Handles layer specific configuration including the wrapped native token.
|
|
64
|
-
/// @param messenger The OPMessenger on this layer.
|
|
65
|
-
/// @param bridge The OPStandardBridge on this layer.
|
|
66
|
-
/// @param _wrappedNative The ERC-20 wrapper for the chain's native token on this layer.
|
|
67
|
-
function setChainSpecificConstants(
|
|
68
|
-
IOPMessenger messenger,
|
|
69
|
-
IOPStandardBridge bridge,
|
|
70
|
-
IWrappedNativeToken _wrappedNative
|
|
71
|
-
)
|
|
72
|
-
external
|
|
73
|
-
{
|
|
74
|
-
// Make sure the layer specific configuration has not already been set.
|
|
75
|
-
if (_layerSpecificConfigurationIsSet()) {
|
|
76
|
-
revert JBSuckerDeployer_AlreadyConfigured({
|
|
77
|
-
singleton: address(singleton), layerSpecificConfigurationIsSet: true
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Make sure only the configurator can call this function.
|
|
82
|
-
if (_msgSender() != LAYER_SPECIFIC_CONFIGURATOR) {
|
|
83
|
-
revert JBSuckerDeployer_Unauthorized({caller: _msgSender(), expected: LAYER_SPECIFIC_CONFIGURATOR});
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Configure these layer specific properties.
|
|
87
|
-
opMessenger = messenger;
|
|
88
|
-
opBridge = bridge;
|
|
89
|
-
wrappedNative = _wrappedNative;
|
|
90
|
-
|
|
91
|
-
// Make sure the layer specific configuration is properly configured.
|
|
92
|
-
if (!_layerSpecificConfigurationIsSet()) {
|
|
93
|
-
revert JBSuckerDeployer_InvalidLayerSpecificConfiguration({configurator: LAYER_SPECIFIC_CONFIGURATOR});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.0;
|
|
3
|
-
|
|
4
|
-
/// @notice Immutable conversion rate for one received root batch, keyed by nonce.
|
|
5
|
-
/// @dev Each batch stores its total leaf and local amounts. Individual claims compute their scaled amount as
|
|
6
|
-
/// `claimLeafAmount * localTotal / leafTotal` — no mutable state changes.
|
|
7
|
-
/// @custom:member leafTotal Total leaf-denomination (source chain) amount for this batch.
|
|
8
|
-
/// @custom:member localTotal Total local-denomination (after swap) amount for this batch.
|
|
9
|
-
struct JBConversionRate {
|
|
10
|
-
uint256 leafTotal;
|
|
11
|
-
uint256 localTotal;
|
|
12
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.0;
|
|
3
|
-
|
|
4
|
-
/// @notice Bridge tokens from a failed inbound swap, stored for later retry via `retrySwap`.
|
|
5
|
-
/// @custom:member bridgeToken The bridge token received from CCIP.
|
|
6
|
-
/// @custom:member bridgeAmount Amount of bridge tokens to swap.
|
|
7
|
-
/// @custom:member leafTotal Original leaf-denomination total (for conversion rate).
|
|
8
|
-
struct JBPendingSwap {
|
|
9
|
-
address bridgeToken;
|
|
10
|
-
uint256 bridgeAmount;
|
|
11
|
-
uint256 leafTotal;
|
|
12
|
-
}
|