@bananapus/suckers-v6 0.0.1

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.
Files changed (149) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +422 -0
  3. package/SECURITY.md +55 -0
  4. package/SKILLS.md +163 -0
  5. package/deployments/nana-suckers-v5/arbitrum/JBArbitrumSucker.json +1425 -0
  6. package/deployments/nana-suckers-v5/arbitrum/JBArbitrumSuckerDeployer.json +391 -0
  7. package/deployments/nana-suckers-v5/arbitrum/JBCCIPSucker.json +1479 -0
  8. package/deployments/nana-suckers-v5/arbitrum/JBCCIPSuckerDeployer.json +433 -0
  9. package/deployments/nana-suckers-v5/arbitrum/JBCCIPSuckerDeployer_1.json +433 -0
  10. package/deployments/nana-suckers-v5/arbitrum/JBCCIPSuckerDeployer_2.json +433 -0
  11. package/deployments/nana-suckers-v5/arbitrum/JBCCIPSucker_1.json +1479 -0
  12. package/deployments/nana-suckers-v5/arbitrum/JBCCIPSucker_2.json +1479 -0
  13. package/deployments/nana-suckers-v5/arbitrum/JBSuckerRegistry.json +690 -0
  14. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBArbitrumSucker.json +1425 -0
  15. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBArbitrumSuckerDeployer.json +391 -0
  16. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSucker.json +1479 -0
  17. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSuckerDeployer.json +433 -0
  18. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSuckerDeployer_1.json +433 -0
  19. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSuckerDeployer_2.json +433 -0
  20. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSucker_1.json +1479 -0
  21. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSucker_2.json +1479 -0
  22. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBSuckerRegistry.json +690 -0
  23. package/deployments/nana-suckers-v5/base/JBBaseSucker.json +1389 -0
  24. package/deployments/nana-suckers-v5/base/JBBaseSuckerDeployer.json +376 -0
  25. package/deployments/nana-suckers-v5/base/JBCCIPSucker.json +1483 -0
  26. package/deployments/nana-suckers-v5/base/JBCCIPSuckerDeployer.json +436 -0
  27. package/deployments/nana-suckers-v5/base/JBCCIPSuckerDeployer_1.json +436 -0
  28. package/deployments/nana-suckers-v5/base/JBCCIPSuckerDeployer_2.json +436 -0
  29. package/deployments/nana-suckers-v5/base/JBCCIPSucker_1.json +1483 -0
  30. package/deployments/nana-suckers-v5/base/JBCCIPSucker_2.json +1483 -0
  31. package/deployments/nana-suckers-v5/base/JBSuckerRegistry.json +694 -0
  32. package/deployments/nana-suckers-v5/base_sepolia/JBBaseSucker.json +1389 -0
  33. package/deployments/nana-suckers-v5/base_sepolia/JBBaseSuckerDeployer.json +376 -0
  34. package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSucker.json +1483 -0
  35. package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSuckerDeployer.json +436 -0
  36. package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSuckerDeployer_1.json +436 -0
  37. package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSuckerDeployer_2.json +436 -0
  38. package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSucker_1.json +1483 -0
  39. package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSucker_2.json +1483 -0
  40. package/deployments/nana-suckers-v5/base_sepolia/JBSuckerRegistry.json +694 -0
  41. package/deployments/nana-suckers-v5/ethereum/JBArbitrumSucker.json +1429 -0
  42. package/deployments/nana-suckers-v5/ethereum/JBArbitrumSuckerDeployer.json +394 -0
  43. package/deployments/nana-suckers-v5/ethereum/JBBaseSucker.json +1389 -0
  44. package/deployments/nana-suckers-v5/ethereum/JBBaseSuckerDeployer.json +376 -0
  45. package/deployments/nana-suckers-v5/ethereum/JBCCIPSucker.json +1483 -0
  46. package/deployments/nana-suckers-v5/ethereum/JBCCIPSuckerDeployer.json +436 -0
  47. package/deployments/nana-suckers-v5/ethereum/JBCCIPSuckerDeployer_1.json +436 -0
  48. package/deployments/nana-suckers-v5/ethereum/JBCCIPSuckerDeployer_2.json +436 -0
  49. package/deployments/nana-suckers-v5/ethereum/JBCCIPSucker_1.json +1483 -0
  50. package/deployments/nana-suckers-v5/ethereum/JBCCIPSucker_2.json +1483 -0
  51. package/deployments/nana-suckers-v5/ethereum/JBOptimismSucker.json +1389 -0
  52. package/deployments/nana-suckers-v5/ethereum/JBOptimismSuckerDeployer.json +376 -0
  53. package/deployments/nana-suckers-v5/ethereum/JBSuckerRegistry.json +694 -0
  54. package/deployments/nana-suckers-v5/optimism/JBCCIPSucker.json +1479 -0
  55. package/deployments/nana-suckers-v5/optimism/JBCCIPSuckerDeployer.json +433 -0
  56. package/deployments/nana-suckers-v5/optimism/JBCCIPSuckerDeployer_1.json +433 -0
  57. package/deployments/nana-suckers-v5/optimism/JBCCIPSuckerDeployer_2.json +433 -0
  58. package/deployments/nana-suckers-v5/optimism/JBCCIPSucker_1.json +1479 -0
  59. package/deployments/nana-suckers-v5/optimism/JBCCIPSucker_2.json +1479 -0
  60. package/deployments/nana-suckers-v5/optimism/JBOptimismSucker.json +1385 -0
  61. package/deployments/nana-suckers-v5/optimism/JBOptimismSuckerDeployer.json +373 -0
  62. package/deployments/nana-suckers-v5/optimism/JBSuckerRegistry.json +690 -0
  63. package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSucker.json +1483 -0
  64. package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSuckerDeployer.json +436 -0
  65. package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSuckerDeployer_1.json +436 -0
  66. package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSuckerDeployer_2.json +436 -0
  67. package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSucker_1.json +1483 -0
  68. package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSucker_2.json +1483 -0
  69. package/deployments/nana-suckers-v5/optimism_sepolia/JBOptimismSucker.json +1389 -0
  70. package/deployments/nana-suckers-v5/optimism_sepolia/JBOptimismSuckerDeployer.json +376 -0
  71. package/deployments/nana-suckers-v5/optimism_sepolia/JBSuckerRegistry.json +694 -0
  72. package/deployments/nana-suckers-v5/sepolia/JBArbitrumSucker.json +1429 -0
  73. package/deployments/nana-suckers-v5/sepolia/JBArbitrumSuckerDeployer.json +394 -0
  74. package/deployments/nana-suckers-v5/sepolia/JBBaseSucker.json +1389 -0
  75. package/deployments/nana-suckers-v5/sepolia/JBBaseSuckerDeployer.json +376 -0
  76. package/deployments/nana-suckers-v5/sepolia/JBCCIPSucker.json +1483 -0
  77. package/deployments/nana-suckers-v5/sepolia/JBCCIPSuckerDeployer.json +436 -0
  78. package/deployments/nana-suckers-v5/sepolia/JBCCIPSuckerDeployer_1.json +436 -0
  79. package/deployments/nana-suckers-v5/sepolia/JBCCIPSuckerDeployer_2.json +436 -0
  80. package/deployments/nana-suckers-v5/sepolia/JBCCIPSucker_1.json +1483 -0
  81. package/deployments/nana-suckers-v5/sepolia/JBCCIPSucker_2.json +1483 -0
  82. package/deployments/nana-suckers-v5/sepolia/JBOptimismSucker.json +1389 -0
  83. package/deployments/nana-suckers-v5/sepolia/JBOptimismSuckerDeployer.json +376 -0
  84. package/deployments/nana-suckers-v5/sepolia/JBSuckerRegistry.json +694 -0
  85. package/foundry.lock +11 -0
  86. package/foundry.toml +22 -0
  87. package/package.json +33 -0
  88. package/remappings.txt +1 -0
  89. package/script/Deploy.s.sol +506 -0
  90. package/script/helpers/SuckerDeploymentLib.sol +97 -0
  91. package/slither-ci.config.json +10 -0
  92. package/sphinx.lock +476 -0
  93. package/src/JBArbitrumSucker.sol +311 -0
  94. package/src/JBBaseSucker.sol +41 -0
  95. package/src/JBCCIPSucker.sol +303 -0
  96. package/src/JBOptimismSucker.sol +143 -0
  97. package/src/JBSucker.sol +1159 -0
  98. package/src/JBSuckerRegistry.sol +262 -0
  99. package/src/deployers/JBArbitrumSuckerDeployer.sol +86 -0
  100. package/src/deployers/JBBaseSuckerDeployer.sol +26 -0
  101. package/src/deployers/JBCCIPSuckerDeployer.sol +88 -0
  102. package/src/deployers/JBOptimismSuckerDeployer.sol +82 -0
  103. package/src/deployers/JBSuckerDeployer.sol +147 -0
  104. package/src/enums/JBAddToBalanceMode.sol +11 -0
  105. package/src/enums/JBLayer.sol +8 -0
  106. package/src/enums/JBSuckerState.sol +14 -0
  107. package/src/interfaces/IArbGatewayRouter.sol +11 -0
  108. package/src/interfaces/IArbL1GatewayRouter.sol +17 -0
  109. package/src/interfaces/IArbL2GatewayRouter.sol +14 -0
  110. package/src/interfaces/ICCIPRouter.sol +11 -0
  111. package/src/interfaces/IJBArbitrumSucker.sol +13 -0
  112. package/src/interfaces/IJBArbitrumSuckerDeployer.sol +12 -0
  113. package/src/interfaces/IJBCCIPSuckerDeployer.sol +15 -0
  114. package/src/interfaces/IJBOpSuckerDeployer.sol +11 -0
  115. package/src/interfaces/IJBOptimismSucker.sol +10 -0
  116. package/src/interfaces/IJBSucker.sol +144 -0
  117. package/src/interfaces/IJBSuckerDeployer.sol +40 -0
  118. package/src/interfaces/IJBSuckerExtended.sol +22 -0
  119. package/src/interfaces/IJBSuckerRegistry.sol +75 -0
  120. package/src/interfaces/IOPMessenger.sol +18 -0
  121. package/src/interfaces/IOPStandardBridge.sol +29 -0
  122. package/src/interfaces/IWrappedNativeToken.sol +13 -0
  123. package/src/libraries/ARBAddresses.sol +17 -0
  124. package/src/libraries/ARBChains.sol +11 -0
  125. package/src/libraries/CCIPHelper.sol +136 -0
  126. package/src/structs/JBClaim.sol +13 -0
  127. package/src/structs/JBInboxTreeRoot.sol +12 -0
  128. package/src/structs/JBLeaf.sol +14 -0
  129. package/src/structs/JBMessageRoot.sol +16 -0
  130. package/src/structs/JBOutboxTree.sol +18 -0
  131. package/src/structs/JBRemoteToken.sol +17 -0
  132. package/src/structs/JBSuckerDeployerConfig.sol +12 -0
  133. package/src/structs/JBSuckersPair.sol +11 -0
  134. package/src/structs/JBTokenMapping.sol +13 -0
  135. package/src/utils/MerkleLib.sol +1020 -0
  136. package/test/Fork.t.sol +514 -0
  137. package/test/InteropCompat.t.sol +676 -0
  138. package/test/SuckerAttacks.t.sol +509 -0
  139. package/test/SuckerDeepAttacks.t.sol +1563 -0
  140. package/test/mocks/ERC20Mock.sol +36 -0
  141. package/test/mocks/MockMessenger.sol +42 -0
  142. package/test/unit/arb.t.sol +28 -0
  143. package/test/unit/ccip_native_interop.t.sol +719 -0
  144. package/test/unit/ccip_refund.t.sol +234 -0
  145. package/test/unit/deployer.t.sol +475 -0
  146. package/test/unit/emergency.t.sol +305 -0
  147. package/test/unit/merkle.t.sol +212 -0
  148. package/test/unit/multi_chain_evolution.t.sol +622 -0
  149. package/test/unit/registry.t.sol +26 -0
@@ -0,0 +1,143 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.23;
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 {IJBTokens} from "@bananapus/core-v6/src/interfaces/IJBTokens.sol";
7
+ import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
8
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
9
+ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
10
+ import {BitMaps} from "@openzeppelin/contracts/utils/structs/BitMaps.sol";
11
+
12
+ import {JBSucker} from "./JBSucker.sol";
13
+ import {JBOptimismSuckerDeployer} from "./deployers/JBOptimismSuckerDeployer.sol";
14
+ import {IJBOptimismSucker} from "./interfaces/IJBOptimismSucker.sol";
15
+ import {IJBSuckerDeployer} from "./interfaces/IJBSuckerDeployer.sol";
16
+ import {IOPMessenger} from "./interfaces/IOPMessenger.sol";
17
+ import {IOPStandardBridge} from "./interfaces/IOPStandardBridge.sol";
18
+ import {JBAddToBalanceMode} from "./enums/JBAddToBalanceMode.sol";
19
+ import {JBInboxTreeRoot} from "./structs/JBInboxTreeRoot.sol";
20
+ import {JBMessageRoot} from "./structs/JBMessageRoot.sol";
21
+ import {JBOutboxTree} from "./structs/JBOutboxTree.sol";
22
+ import {JBRemoteToken} from "./structs/JBRemoteToken.sol";
23
+ import {MerkleLib} from "./utils/MerkleLib.sol";
24
+
25
+ /// @notice A `JBSucker` implementation to suck tokens between two chains connected by an OP Bridge.
26
+ contract JBOptimismSucker is JBSucker, IJBOptimismSucker {
27
+ using BitMaps for BitMaps.BitMap;
28
+ using MerkleLib for MerkleLib.Tree;
29
+
30
+ //*********************************************************************//
31
+ // --------------- public immutable stored properties ---------------- //
32
+ //*********************************************************************//
33
+
34
+ /// @notice The bridge used to bridge tokens between the local and remote chain.
35
+ IOPStandardBridge public immutable override OPBRIDGE;
36
+
37
+ /// @notice The messenger used to send messages between the local and remote sucker.
38
+ IOPMessenger public immutable override OPMESSENGER;
39
+
40
+ //*********************************************************************//
41
+ // ---------------------------- constructor -------------------------- //
42
+ //*********************************************************************//
43
+
44
+ /// @param deployer A contract that deploys the clones for this contracts.
45
+ /// @param directory A contract storing directories of terminals and controllers for each project.
46
+ /// @param tokens A contract that manages token minting and burning.
47
+ /// @param permissions A contract storing permissions.
48
+ /// @param addToBalanceMode The mode of adding tokens to balance.
49
+ constructor(
50
+ JBOptimismSuckerDeployer deployer,
51
+ IJBDirectory directory,
52
+ IJBPermissions permissions,
53
+ IJBTokens tokens,
54
+ JBAddToBalanceMode addToBalanceMode,
55
+ address trustedForwarder
56
+ )
57
+ JBSucker(directory, permissions, tokens, addToBalanceMode, trustedForwarder)
58
+ {
59
+ // Fetch the messenger and bridge by doing a callback to the deployer contract.
60
+ OPBRIDGE = JBOptimismSuckerDeployer(deployer).opBridge();
61
+ OPMESSENGER = JBOptimismSuckerDeployer(deployer).opMessenger();
62
+ }
63
+
64
+ //*********************************************************************//
65
+ // ------------------------ external views --------------------------- //
66
+ //*********************************************************************//
67
+
68
+ /// @notice Returns the chain on which the peer is located.
69
+ /// @return chainId of the peer.
70
+ function peerChainId() external view virtual override returns (uint256) {
71
+ uint256 chainId = block.chainid;
72
+ if (chainId == 1) return 10;
73
+ if (chainId == 10) return 1;
74
+ if (chainId == 11_155_111) return 11_155_420;
75
+ if (chainId == 11_155_420) return 11_155_111;
76
+ return 0;
77
+ }
78
+
79
+ //*********************************************************************//
80
+ // --------------------- internal transactions ----------------------- //
81
+ //*********************************************************************//
82
+
83
+ /// @notice Checks if the `sender` (`_msgSender()`) is a valid representative of the remote peer.
84
+ /// @param sender The message's sender.
85
+ function _isRemotePeer(address sender) internal override returns (bool valid) {
86
+ return sender == address(OPMESSENGER) && _toBytes32(OPMESSENGER.xDomainMessageSender()) == peer();
87
+ }
88
+
89
+ /// @notice Use the `OPMESSENGER` to send the outbox tree for the `token` and the corresponding funds to the peer
90
+ /// over the `OPBRIDGE`.
91
+ /// @param transportPayment the amount of `msg.value` that is going to get paid for sending this message.
92
+ /// @param token The token to bridge the outbox tree for.
93
+ /// @param remoteToken Information about the remote token being bridged to.
94
+ function _sendRootOverAMB(
95
+ uint256 transportPayment,
96
+ uint256,
97
+ address token,
98
+ uint256 amount,
99
+ JBRemoteToken memory remoteToken,
100
+ JBMessageRoot memory message
101
+ )
102
+ internal
103
+ override
104
+ {
105
+ uint256 nativeValue;
106
+
107
+ // Revert if there's a `msg.value`. The OP bridge does not expect to be paid.
108
+ if (transportPayment != 0) {
109
+ revert JBSucker_UnexpectedMsgValue(transportPayment);
110
+ }
111
+
112
+ // If the token is an ERC20, bridge it to the peer.
113
+ // If the amount is `0` then we do not need to bridge any ERC20.
114
+ if (token != JBConstants.NATIVE_TOKEN && amount != 0) {
115
+ // Approve the tokens being bridged.
116
+ // slither-disable-next-line reentrancy-events
117
+ SafeERC20.forceApprove({token: IERC20(token), spender: address(OPBRIDGE), value: amount});
118
+
119
+ // Bridge the tokens to the peer sucker. Convert bytes32 types to address at the OP Bridge API boundary.
120
+ // slither-disable-next-line reentrancy-events,calls-loop
121
+ OPBRIDGE.bridgeERC20To({
122
+ localToken: token,
123
+ remoteToken: _toAddress(remoteToken.addr),
124
+ to: _toAddress(peer()),
125
+ amount: amount,
126
+ minGasLimit: remoteToken.minGas,
127
+ extraData: bytes("")
128
+ });
129
+ } else {
130
+ // Otherwise, the token is the native token, and the amount will be sent as `msg.value`.
131
+ nativeValue = amount;
132
+ }
133
+
134
+ // Send the message to the peer with the reclaimed ETH.
135
+ // Convert bytes32 peer to address at the OP Messenger API boundary.
136
+ // slither-disable-next-line arbitrary-send-eth,reentrancy-events,calls-loop
137
+ OPMESSENGER.sendMessage{value: nativeValue}({
138
+ target: _toAddress(peer()),
139
+ message: abi.encodeCall(JBSucker.fromRemote, (message)),
140
+ gasLimit: MESSENGER_BASE_GAS_LIMIT
141
+ });
142
+ }
143
+ }