@bananapus/suckers-v6 0.0.71 → 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 +11 -11
- package/package.json +9 -8
- package/references/operations.md +5 -5
- package/references/runtime.md +5 -5
- package/src/JBArbitrumSucker.sol +2 -0
- package/src/JBCCIPSucker.sol +11 -0
- package/src/JBOptimismSucker.sol +1 -0
- package/src/JBSucker.sol +88 -35
- package/src/JBSuckerRegistry.sol +16 -8
- package/src/deployers/JBSuckerDeployer.sol +15 -1
- package/src/interfaces/IJBSucker.sol +3 -2
- package/src/interfaces/IJBSuckerRegistry.sol +1 -2
- package/src/libraries/CCIPHelper.sol +1 -0
- package/src/libraries/JBSuckerLib.sol +5 -8
- package/src/structs/JBInboxTreeRoot.sol +1 -2
- package/src/utils/MerkleLib.sol +3 -1
- 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 -735
- package/src/archive/JBSwapCCIPSuckerDeployer.sol +0 -115
- package/src/archive/JBSwapLib.sol +0 -148
- package/src/archive/JBSwapPoolLib.sol +0 -1129
|
@@ -26,11 +26,23 @@ abstract contract JBSuckerDeployer is ERC2771Context, JBPermissioned, IJBSuckerD
|
|
|
26
26
|
// --------------------------- custom errors ------------------------- //
|
|
27
27
|
//*********************************************************************//
|
|
28
28
|
|
|
29
|
+
/// @notice Thrown when configuration is attempted but the deployer (singleton or layer-specific config) has already
|
|
30
|
+
/// been configured.
|
|
29
31
|
error JBSuckerDeployer_AlreadyConfigured(address singleton, bool layerSpecificConfigurationIsSet);
|
|
32
|
+
|
|
33
|
+
/// @notice Thrown when a sucker is deployed before the deployer's singleton implementation has been set.
|
|
30
34
|
error JBSuckerDeployer_DeployerIsNotConfigured(address singleton);
|
|
35
|
+
|
|
36
|
+
/// @notice Thrown when the layer-specific configuration is not properly set after configuration.
|
|
31
37
|
error JBSuckerDeployer_InvalidLayerSpecificConfiguration(address configurator);
|
|
38
|
+
|
|
39
|
+
/// @notice Thrown when a sucker is deployed before the layer-specific configuration has been set.
|
|
32
40
|
error JBSuckerDeployer_LayerSpecificNotConfigured(address configurator);
|
|
41
|
+
|
|
42
|
+
/// @notice Thrown when the caller is not the address authorized to configure this deployer.
|
|
33
43
|
error JBSuckerDeployer_Unauthorized(address caller, address expected);
|
|
44
|
+
|
|
45
|
+
/// @notice Thrown when the configurator address provided is the zero address.
|
|
34
46
|
error JBSuckerDeployer_ZeroConfiguratorAddress(address configurator);
|
|
35
47
|
|
|
36
48
|
//*********************************************************************//
|
|
@@ -51,9 +63,11 @@ abstract contract JBSuckerDeployer is ERC2771Context, JBPermissioned, IJBSuckerD
|
|
|
51
63
|
//*********************************************************************//
|
|
52
64
|
|
|
53
65
|
/// @notice Whether a given address was deployed by this deployer.
|
|
54
|
-
|
|
66
|
+
/// @custom:param sucker The address to check.
|
|
67
|
+
mapping(address sucker => bool) public override isSucker;
|
|
55
68
|
|
|
56
69
|
/// @notice The singleton used to clone suckers.
|
|
70
|
+
/// @dev Write-once via `configureSingleton`; the clone implementation for every sucker this deployer produces.
|
|
57
71
|
JBSucker public singleton;
|
|
58
72
|
|
|
59
73
|
//*********************************************************************//
|
|
@@ -24,6 +24,7 @@ interface IJBSucker is IERC165 {
|
|
|
24
24
|
/// @param projectTokenCount The number of project tokens claimed.
|
|
25
25
|
/// @param terminalTokenAmount The amount of terminal tokens involved.
|
|
26
26
|
/// @param index The leaf index in the inbox tree.
|
|
27
|
+
/// @param metadata The opaque, caller-defined payload carried by the claimed leaf.
|
|
27
28
|
/// @param caller The address that performed the claim.
|
|
28
29
|
event Claimed(
|
|
29
30
|
bytes32 beneficiary,
|
|
@@ -52,6 +53,7 @@ interface IJBSucker is IERC165 {
|
|
|
52
53
|
/// @param root The new outbox tree root after insertion.
|
|
53
54
|
/// @param projectTokenCount The number of project tokens cashed out.
|
|
54
55
|
/// @param terminalTokenAmount The amount of terminal tokens reclaimed.
|
|
56
|
+
/// @param metadata The opaque, caller-defined payload carried by the outbox leaf.
|
|
55
57
|
/// @param caller The address that performed the insertion.
|
|
56
58
|
event InsertToOutboxTree(
|
|
57
59
|
bytes32 indexed beneficiary,
|
|
@@ -220,8 +222,7 @@ interface IJBSucker is IERC165 {
|
|
|
220
222
|
/// @param token The terminal token to cash out into.
|
|
221
223
|
/// @param metadata Opaque caller-defined attribution payload included in the leaf hash. The sucker protocol does
|
|
222
224
|
/// not inspect this value — it's covered by the merkle root, so the destination contract that consumes the claim
|
|
223
|
-
/// can
|
|
224
|
-
/// 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.
|
|
225
226
|
function prepare(
|
|
226
227
|
uint256 projectTokenCount,
|
|
227
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.
|
|
@@ -3,6 +3,7 @@ pragma solidity 0.8.28;
|
|
|
3
3
|
|
|
4
4
|
/// @notice CCIP chain-specific constants used across Juicebox sucker contracts.
|
|
5
5
|
library CCIPHelper {
|
|
6
|
+
/// @notice Thrown when a lookup is requested for a chain ID that has no configured CCIP constants.
|
|
6
7
|
error CCIPHelper_UnsupportedChain(uint256 chainId);
|
|
7
8
|
/// @notice The CCIP router address for Ethereum mainnet.
|
|
8
9
|
address public constant ETH_ROUTER = 0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D;
|
|
@@ -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 {
|
package/src/utils/MerkleLib.sol
CHANGED
|
@@ -5,6 +5,7 @@ pragma solidity 0.8.28;
|
|
|
5
5
|
* @title MerkleLib
|
|
6
6
|
* @author Illusory Systems Inc.
|
|
7
7
|
* @notice An incremental merkle tree modeled on the eth2 deposit contract.
|
|
8
|
+
* @dev Vendored upstream library; its Doxygen-style NatSpec deviates from the repo's `///` house style.
|
|
8
9
|
*
|
|
9
10
|
*/
|
|
10
11
|
library MerkleLib {
|
|
@@ -12,6 +13,7 @@ library MerkleLib {
|
|
|
12
13
|
// --------------------------- custom errors ------------------------- //
|
|
13
14
|
//*********************************************************************//
|
|
14
15
|
|
|
16
|
+
/// @notice Thrown when a leaf is inserted into a merkle tree that has already reached its maximum number of leaves.
|
|
15
17
|
error MerkleLib_InsertTreeIsFull(uint256 size, uint256 maxLeaves);
|
|
16
18
|
|
|
17
19
|
//*********************************************************************//
|
|
@@ -82,7 +84,7 @@ library MerkleLib {
|
|
|
82
84
|
/**
|
|
83
85
|
* @notice Inserts a given node (leaf) into the merkle tree in storage.
|
|
84
86
|
* @dev Operates directly on storage, writing only the single branch entry that changes (plus count).
|
|
85
|
-
* This
|
|
87
|
+
* This writes only the changed branch slot instead of round-tripping all 33 slots through memory.
|
|
86
88
|
* @dev Reverts if the tree is already full.
|
|
87
89
|
* @param tree The storage reference to the tree.
|
|
88
90
|
* @param node Element to insert into tree.
|
|
@@ -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
|
-
}
|