This is the top-ranked automated findings report, from IllIllI-bot bot. All findings in this report will be considered known issues for the purposes of your C4 audit.
Note: There is a section for disputed findings below the usual findings sections
Issue | Instances | |
---|---|---|
[M‑01] | Unchecked return value of low-level call() /delegatecall() |
3 |
[M‑02] | Use of transferFrom() rather than safeTransferFrom() for NFTs in will lead to the loss of NFTs |
1 |
[M‑03] | The owner is a single point of failure and a centralization risk |
38 |
[M‑04] | Return values of approve() not checked |
1 |
Total: 43 instances over 4 issues
Issue | Instances | |
---|---|---|
[L‑01] | addStrategyToken() does note remove old entries before adding new ones |
2 |
[L‑02] | Unsafe downcast | 8 |
[L‑03] | Array lengths not checked | 1 |
[L‑04] | receive() /payable fallback() function does not authorize requests |
3 |
[L‑05] | safeApprove() is deprecated |
2 |
[L‑06] | Use Ownable2Step rather than Ownable |
12 |
[L‑07] | Empty receive() /fallback() function |
3 |
[L‑08] | External calls in an un-bounded for- loop may result in a DOS |
4 |
[L‑09] | Consider implementing two-step procedure for updating protocol addresses | 10 |
[L‑10] | name() is not a part of the ERC-20 standard |
5 |
[L‑11] | symbol() is not a part of the ERC-20 standard |
5 |
[L‑12] | decimals() is not a part of the ERC-20 standard |
4 |
[L‑13] | SafeTransferLib does not ensure that the token contract exists |
2 |
[L‑14] | Functions calling contracts/addresses with transfer hooks are missing reentrancy guards | 1 |
[L‑15] | approve() /safeApprove() may revert if the current approval is not zero |
3 |
[L‑16] | External call recipient may consume all transaction gas | 8 |
[L‑17] | Missing contract-existence checks before low-level calls | 4 |
[L‑18] | Code does not follow the best practice of check-effects-interaction | 43 |
[L‑19] | Missing checks for address(0x0) in the constructor/initializer |
7 |
[L‑20] | Missing checks for address(0x0) when updating address state variables |
1 |
[L‑21] | State variables not capped at reasonable values | 2 |
[L‑22] | Tokens may be minted to address(0x0) |
2 |
[L‑23] | Initialization can be front-run | 8 |
Total: 140 instances over 23 issues
Issue | Instances | |
---|---|---|
[N‑01] | public functions not called by the contract should be declared external instead |
6 |
[N‑02] | Event is not properly indexed |
1 |
[N‑03] | Duplicated require() /revert() checks should be refactored to a modifier or function |
12 |
[N‑04] | Common functions should be refactored to a common base contract | 1 |
[N‑05] | Import declarations should import specific identifiers, rather than the whole file | 1 |
[N‑06] | Events that mark critical parameter changes should contain both the old and the new value | 6 |
[N‑07] | Constant redefined elsewhere | 25 |
[N‑08] | Inconsistent spacing in comments | 145 |
[N‑09] | Lines are too long | 32 |
[N‑10] | Long functions should be refactored into multiple, smaller, functions | 13 |
[N‑11] | Inconsistent method of specifying a floating pragma | 3 |
[N‑12] | Using > />= without specifying an upper bound is unsafe |
3 |
[N‑13] | Typos | 37 |
[N‑14] | File is missing NatSpec | 3 |
[N‑15] | Function definition modifier order does not follow Solidity style guide | 2 |
[N‑16] | Assembly blocks should have extensive comments | 1 |
[N‑17] | Visibility should be set explicitly rather than defaulting to internal |
3 |
[N‑18] | Function ordering does not follow the Solidity style guide | 11 |
[N‑19] | Contract does not follow the Solidity style guide's suggested layout ordering | 15 |
[N‑20] | Add inline comments for unnamed variables | 18 |
[N‑21] | Invalid NatSpec comment style | 67 |
[N‑22] | Contracts should have full test coverage | 1 |
[N‑23] | Large or complicated code bases should implement invariant tests | 1 |
[N‑24] | Consider adding formal verification proofs | 1 |
[N‑25] | Multiple address /ID mappings can be combined into a single mapping of an address /ID to a struct , for readability |
3 |
[N‑26] | Custom errors should be used rather than revert() /require() |
54 |
[N‑27] | Use abi.encodeCall() instead of abi.encodeWithSignature() /abi.encodeWithSelector() |
12 |
[N‑28] | Style guide: Non-external /public variable names should begin with an underscore |
23 |
[N‑29] | Variable names for immutable s should use CONSTANT_CASE |
39 |
[N‑30] | Array indicies should be referenced via enum s rather than via numeric literals |
66 |
[N‑31] | Consider using named mappings | 40 |
[N‑32] | Use of override is unnecessary |
117 |
[N‑33] | Consider using descriptive constant s when passing zero as a function argument |
4 |
[N‑34] | Variables need not be initialized to zero | 17 |
[N‑35] | require() /revert() statements should have descriptive reason strings |
13 |
[N‑36] | Contracts/libraries should each be defined in separate files | 4 |
[N‑37] | Contract uses both require() /revert() as well as custom errors |
10 |
[N‑38] | Contract doesn't handle all NFT types | 2 |
[N‑39] | Style guide: Non-external /public function names should begin with an underscore |
2 |
[N‑40] | constant s should be defined rather than using magic numbers |
125 |
[N‑41] | Events are missing sender information | 27 |
[N‑42] | Consider adding a block/deny-list | 12 |
[N‑43] | Consider using SafeTransferLib.safeTransferETH() or Address.sendValue() for clearer semantic meaning |
3 |
[N‑44] | Unused import | 15 |
[N‑45] | Array is push() ed but not pop() ed |
12 |
[N‑46] | Unused struct definition |
1 |
[N‑47] | Unused error definition |
7 |
[N‑48] | NatSpec: Contract declarations should have NatSpec descriptions | 4 |
[N‑49] | NatSpec: Contract declarations should have @notice tags |
4 |
[N‑50] | NatSpec: Error declarations should have NatSpec descriptions | 90 |
[N‑51] | NatSpec: Event declarations should have NatSpec descriptions | 28 |
[N‑52] | NatSpec: State variable declarations should have NatSpec descriptions | 22 |
[N‑53] | NatSpec: Function declarations should have NatSpec descriptions | 37 |
[N‑54] | NatSpec: Function declarations should have @notice tags |
37 |
[N‑55] | Constants in comparisons should appear on the left side | 62 |
[N‑56] | Custom error has no error details | 90 |
[N‑57] | NatSpec: Contract declarations should have @author tags |
9 |
[N‑58] | NatSpec: Contract declarations should have @dev tags |
34 |
[N‑59] | NatSpec: Contract declarations should have @title tags |
4 |
[N‑60] | Empty function body | 1 |
[N‑61] | Use bytes.concat() on bytes instead of abi.encodePacked() for clearer semantic meaning |
14 |
[N‑62] | if -statement can be converted to a ternary |
2 |
[N‑63] | Overflows in unchecked blocks | 15 |
[N‑64] | Consider splitting long calculations | 8 |
[N‑65] | Contract should expose an interface |
47 |
[N‑66] | else -block not required |
2 |
[N‑67] | Missing event and or timelock for critical parameter change | 1 |
[N‑68] | Setters should prevent re-setting of the same value | 11 |
[N‑69] | Polymorphic functions make security audits more time-consuming and error-prone | 6 |
[N‑70] | Imports could be organized more systematically | 4 |
[N‑71] | Use the latest solidity (prior to 0.8.20 if on L2s) for deployment | 23 |
[N‑72] | Consider moving msg.sender checks to a common authorization modifier |
7 |
[N‑73] | Non-library/interface files should use fixed compiler versions, not floating ones | 23 |
[N‑74] | Consider adding emergency-stop functionality | 13 |
[N‑75] | NatSpec: Function @return is missing |
46 |
[N‑76] | NatSpec: Function @param is missing |
111 |
[N‑77] | Consider bounding input array length | 7 |
[N‑78] | Named imports of parent contracts are missing | 1 |
[N‑79] | Complex casting | 59 |
[N‑80] | Events may be emitted out of order due to reentrancy | 7 |
[N‑81] | Non-assembly method available | 1 |
[N‑82] | Missing checks constructor/initializer assignments | 9 |
Total: 1855 instances over 82 issues
Issue | Instances | Total Gas Saved | |
---|---|---|---|
[G‑01] | Enable IR-based code generation | 1 | - |
[G‑02] | Multiple address /ID mappings can be combined into a single mapping of an address /ID to a struct , where appropriate |
5 | - |
[G‑03] | State variables only set in the constructor should be declared immutable |
3 | 6291 |
[G‑04] | Avoid contract existence checks by using low-level calls | 52 | 5200 |
[G‑05] | State variables should be cached in stack variables rather than re-reading them from storage | 1 | 97 |
[G‑06] | internal functions only called once can be inlined to save gas |
14 | 280 |
[G‑07] | <array>.length should not be looked up in every loop of a for -loop |
8 | 24 |
[G‑08] | require() /revert() strings longer than 32 bytes cost extra gas |
22 | 66 |
[G‑09] | Optimize names to save gas | 24 | 528 |
[G‑10] | ++i costs less gas than i++ , especially when it's used in for -loops (--i /i-- too) |
1 | 5 |
[G‑11] | Usage of uints /ints smaller than 32 bytes (256 bits) incurs overhead |
21 | 462 |
[G‑12] | Using private rather than public for constants, saves gas |
12 | - |
[G‑13] | Inverting the condition of an if -else -statement wastes gas |
1 | - |
[G‑14] | require() or revert() statements that check input arguments should be at the top of the function |
11 | - |
[G‑15] | Use custom errors rather than revert() /require() strings to save gas |
49 | - |
[G‑16] | Functions guaranteed to revert when called by normal users can be marked payable |
21 | 441 |
[G‑17] | Constructors can be marked payable |
22 | 462 |
[G‑18] | Reduce gas usage by moving to Solidity 0.8.19 or later | 44 | - |
[G‑19] | >= costs less gas than > |
33 | 99 |
[G‑20] | Nesting if -statements is cheaper than using && |
1 | 6 |
[G‑21] | Use assembly to emit events, in order to save gas | 19 | 722 |
[G‑22] | Use += for mapping s |
5 | 200 |
[G‑23] | Using bool s for storage incurs overhead |
13 | 1300 |
[G‑24] | Use uint256(1) /uint256(2) instead of true /false to save gas for changes |
13 | 222300 |
[G‑25] | Simple checks for zero can be done using assembly to save gas | 25 | 150 |
[G‑26] | Avoid updating storage when the value hasn't changed | 11 | 8800 |
[G‑27] | unchecked {} can be used on the division of two uint s in order to save gas |
1 | 20 |
[G‑28] | Using this to access functions results in an external call, wasting gas |
2 | 200 |
[G‑29] | Use assembly for small keccak256 hashes, in order to save gas | 1 | 80 |
[G‑30] | Using calldata instead of memory for read-only arguments in external functions saves gas |
23 | 2760 |
[G‑31] | Avoid transferring amounts of zero in order to save gas | 10 | 1000 |
[G‑32] | Avoid fetching a low-level call's return data by using assembly | 9 | 1431 |
Total: 478 instances over 32 issues with 252924 gas saved
Gas totals are estimates based on data from the Ethereum Yellowpaper. The estimates use the lower bounds of ranges and count two iterations of each for
-loop. All values above are runtime, not deployment, values; deployment values are listed in the individual issue descriptions. The table above as well as its gas numbers do not include any of the excluded findings.
The issues below may be reported by other bots/wardens, but can be penalized/ignored since either the rule or the specified instances are invalid
Issue | Instances | |
---|---|---|
[D‑01] | call() /delegatecall() |
9 |
[D‑02] | approve() not checked |
1 |
[D‑03] | 5 | |
[D‑04] | 1 | |
[D‑05] | PUSH0 |
44 |
[D‑06] | approve() /safeApprove() may revert if the current approval is not zero |
1 |
[D‑07] | 27 | |
[D‑08] | 12 | |
[D‑09] | require() /revert() checks should be refactored to a modifier or function |
56 |
[D‑10] | 44 | |
[D‑11] | 18 | |
[D‑12] | 3 | |
[D‑13] | 6 | |
[D‑14] | require() / revert() statements should have descriptive reason strings |
155 |
[D‑15] | 3 | |
[D‑16] | @notice tags |
44 |
[D‑17] | 28 | |
[D‑18] | 3 | |
[D‑19] | @notice tags |
305 |
[D‑20] | 2 | |
[D‑21] | 10 | |
[D‑22] | 21 | |
[D‑23] | 99 | |
[D‑24] | 1 | |
[D‑25] | safeApprove() |
2 |
[D‑26] | assembly to write address/contract type storage values |
25 |
[D‑27] | require() and if statements instead of && |
1 |
[D‑28] | 117 | |
[D‑29] | 9 | |
[D‑30] | bytes or bytes32 for clearer semantic meaning |
42 |
[D‑31] | 1 | |
[D‑32] | 6 | |
[D‑33] | bytes.concat() on bytes instead of abi.encodePacked() for clearer semantic meaning |
28 |
[D‑34] | @inheritdoc rather than using a non-standard annotation |
10 |
[D‑35] | 4 | |
[D‑36] | 5 | |
[D‑37] | 4 | |
[D‑38] | selfbalance() is cheaper than address(this).balance |
9 |
[D‑39] | interface |
4 |
[D‑40] | 1 | |
[D‑41] | 1 | |
[D‑42] | abi.encode() is less efficient than abi.encodepacked() |
15 |
[D‑43] | 4 | |
[D‑44] | 15 | |
[D‑45] | this to access functions results in an external call, wasting gas |
5 |
[D‑46] | storage instead of memory for structs/arrays saves gas |
14 |
[D‑47] | 2 | |
[D‑48] | 15 | |
[D‑49] | 49 | |
[D‑50] | 1 | |
[D‑51] | 4 | |
[D‑52] | 17 | |
[D‑53] | 10 | |
[D‑54] | SafeTransferLib does not ensure that the token contract exists |
6 |
[D‑55] | _safeMint instead of _mint for ERC721 |
2 |
[D‑56] | bool values are manually reset |
21 |
[D‑57] | 21 | |
[D‑58] | 21 | |
[D‑59] | calldata instead of memory for read-only arguments in external functions saves gas |
8 |
[D‑60] | 15 | |
[D‑61] | 3 | |
[D‑62] | 14 | |
[D‑63] | 4 | |
[D‑64] | public function visibility to external to save gas |
2 |
[D‑65] | 18 | |
[D‑66] | 1 | |
[D‑67] | 2 | |
[D‑68] | 187 | |
[D‑69] | 3 | |
[D‑70] | event definition |
28 |
[D‑71] | error definition |
73 |
[D‑72] | struct definition |
15 |
[D‑73] | internal functions not called by the contract should be removed |
6 |
[D‑74] | 20 | |
[D‑75] | 1 |
Total: 1789 instances over 75 issues
The function being called may revert, which will be indicated by the return value to call()
/delegatecall()
. If the return value is not checked, the code will continue on as if there was no error, rather than reverting with the error encountered.
There are 3 instances of this issue:
File: src/ArbitrumBranchBridgeAgent.sol
103: _rootBridgeAgentAddress.call{value: msg.value}("");
GitHub: 103
File: src/RootBridgeAgent.sol
835: callee.call{value: msg.value}("");
927: callee.call{value: _value}("");
[M‑02] Use of transferFrom()
rather than safeTransferFrom()
for NFTs in will lead to the loss of NFTs
The EIP-721 standard says the following about transferFrom()
:
/// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
/// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
/// THEY MAY BE PERMANENTLY LOST
/// @dev Throws unless `msg.sender` is the current owner, an authorized
/// operator, or the approved address for this NFT. Throws if `_from` is
/// not the current owner. Throws if `_to` is the zero address. Throws if
/// `_tokenId` is not a valid NFT.
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
Code must use the safeTransferFrom()
flavor if it hasn't otherwise verified that the receiving address can handle it
There is one instance of this issue:
File: src/VirtualAccount.sol
62: ERC721(_token).transferFrom(address(this), msg.sender, _tokenId);
GitHub: 62
Having a single EOA as the only owner of contracts is a large centralization risk and a single point of failure. A single private key may be taken in a hack, or the sole holder of the key may become unable to retrieve the key when necessary, or the single owner can become malicious and perform a rug-pull. Consider changing to a multi-signature setup, and or having a role-based authorization model.
There are 38 instances of this issue:
see instances
File: src/BaseBranchRouter.sol
60: function initialize(address _localBridgeAgentAddress) external onlyOwner {
GitHub: 60
File: src/BranchBridgeAgentExecutor.sol
53: function executeNoSettlement(address _router, bytes calldata _payload) external payable onlyOwner {
66 function executeWithSettlement(address _recipient, address _router, bytes calldata _payload)
67 external
68 payable
69 onlyOwner
70: {
104 function executeWithSettlementMultiple(address _recipient, address _router, bytes calldata _payload)
105 external
106 payable
107 onlyOwner
108: {
File: src/BranchPort.sol
122: function initialize(address _coreBranchRouter, address _bridgeAgentFactory) external virtual onlyOwner {
135: function renounceOwnership() public payable override onlyOwner {
File: src/CoreRootRouter.sol
83: function initialize(address _bridgeAgentAddress, address _hTokenFactory) external onlyOwner {
156 function toggleBranchBridgeAgentFactory(
157 address _rootBridgeAgentFactory,
158 address _branchBridgeAgentFactory,
159 address _refundee,
160 uint16 _dstChainId,
161 GasParams calldata _gParams
162: ) external payable onlyOwner {
186 function removeBranchBridgeAgent(
187 address _branchBridgeAgent,
188 address _refundee,
189 uint16 _dstChainId,
190 GasParams calldata _gParams
191: ) external payable onlyOwner {
212 function manageStrategyToken(
213 address _underlyingToken,
214 uint256 _minimumReservesRatio,
215 address _refundee,
216 uint16 _dstChainId,
217 GasParams calldata _gParams
218: ) external payable onlyOwner {
241 function managePortStrategy(
242 address _portStrategy,
243 address _underlyingToken,
244 uint256 _dailyManagementLimit,
245 bool _isUpdateDailyLimit,
246 address _refundee,
247 uint16 _dstChainId,
248 GasParams calldata _gParams
249: ) external payable onlyOwner {
GitHub: 83, 156, 186, 212, 241
File: src/MulticallRootRouter.sol
109: function initialize(address _bridgeAgentAddress) external onlyOwner {
GitHub: 109
File: src/RootBridgeAgentExecutor.sol
50 function executeSystemRequest(address _router, bytes calldata _payload, uint16 _srcChainId)
51 external
52 payable
53 onlyOwner
54: {
66 function executeNoDeposit(address _router, bytes calldata _payload, uint16 _srcChainId)
67 external
68 payable
69 onlyOwner
70: {
82 function executeWithDeposit(address _router, bytes calldata _payload, uint16 _srcChainId)
83 external
84 payable
85 onlyOwner
86: {
115 function executeWithDepositMultiple(address _router, bytes calldata _payload, uint16 _srcChainId)
116 external
117 payable
118 onlyOwner
119: {
150 function executeSignedNoDeposit(address _account, address _router, bytes calldata _payload, uint16 _srcChainId)
151 external
152 payable
153 onlyOwner
154: {
167 function executeSignedWithDeposit(address _account, address _router, bytes calldata _payload, uint16 _srcChainId)
168 external
169 payable
170 onlyOwner
171: {
201 function executeSignedWithDepositMultiple(
202 address _account,
203 address _router,
204 bytes calldata _payload,
205 uint16 _srcChainId
206: ) external payable onlyOwner {
GitHub: 50, 66, 82, 115, 150, 167, 201
File: src/RootPort.sol
129: function initialize(address _bridgeAgentFactory, address _coreRootRouter) external onlyOwner {
147 function initializeCore(
148 address _coreRootBridgeAgent,
149 address _coreLocalBranchBridgeAgent,
150 address _localBranchPortAddress
151: ) external onlyOwner {
166: function renounceOwnership() public payable override onlyOwner {
414: function toggleBridgeAgent(address _bridgeAgent) external override onlyOwner {
421: function addBridgeAgentFactory(address _bridgeAgentFactory) external override onlyOwner {
431: function toggleBridgeAgentFactory(address _bridgeAgentFactory) external override onlyOwner {
438 function addNewChain(
439 address _coreBranchBridgeAgentAddress,
440 uint256 _chainId,
441 string memory _wrappedGasTokenName,
442 string memory _wrappedGasTokenSymbol,
443 uint8 _wrappedGasTokenDecimals,
444 address _newLocalBranchWrappedNativeTokenAddress,
445 address _newUnderlyingBranchWrappedNativeTokenAddress
446: ) external override onlyOwner {
483: function addEcosystemToken(address _ecoTokenGlobalAddress) external override onlyOwner {
509: function setCoreRootRouter(address _coreRootRouter, address _coreRootBridgeAgent) external override onlyOwner {
521 function setCoreBranchRouter(
522 address _refundee,
523 address _coreBranchRouter,
524 address _coreBranchBridgeAgent,
525 uint16 _dstChainId,
526 GasParams calldata _gParams
527: ) external payable override onlyOwner {
539 function syncNewCoreBranchRouter(address _coreBranchRouter, address _coreBranchBridgeAgent, uint16 _dstChainId)
540 external
541 override
542 onlyOwner
543: {
GitHub: 129, 147, 166, 414, 421, 431, 438, 483, 509, 521, 539
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
56: function initialize(address _coreRootBridgeAgent) external override onlyOwner {
GitHub: 56
File: src/factories/BranchBridgeAgentFactory.sol
87: function initialize(address _coreRootBridgeAgent) external virtual onlyOwner {
GitHub: 87
File: src/factories/ERC20hTokenBranchFactory.sol
60: function initialize(address _wrappedNativeTokenAddress, address _coreRouter) external onlyOwner {
GitHub: 60
File: src/factories/ERC20hTokenRootFactory.sol
49: function initialize(address _coreRouter) external onlyOwner {
GitHub: 49
File: src/token/ERC20hTokenBranch.sol
29: function mint(address account, uint256 amount) external override onlyOwner returns (bool) {
35: function burn(uint256 amount) public override onlyOwner {
File: src/token/ERC20hTokenRoot.sol
57: function mint(address to, uint256 amount, uint256 chainId) external onlyOwner returns (bool) {
69: function burn(address from, uint256 amount, uint256 chainId) external onlyOwner {
Not all IERC20
implementations revert()
when there's a failure in approve()
. The function signature has a boolean
return value and they indicate errors that way instead. By not checking the return value, operations that should have marked as failed, may potentially go through without actually approving anything
There is one instance of this issue:
File: src/BaseBranchRouter.sol
175: ERC20(_token).approve(_localPortAddress, _deposit);
GitHub: 175
Each time addStrategyToken()
is called, new entries are added to the array, but doing so does not remove any old entries. By calling the function multiple times, an attacker can can increase their voting power indefinitely, without having to acquire new tokens.
There are 2 instances of this issue:
File: src/BranchPort.sol
361 /// @inheritdoc IBranchPort
362 function addStrategyToken(address _token, uint256 _minimumReservesRatio) external override requiresCoreRouter {
363 if (_minimumReservesRatio >= DIVISIONER || _minimumReservesRatio < MIN_RESERVE_RATIO) {
364 revert InvalidMinimumReservesRatio();
365 }
366
367 strategyTokens.push(_token);
368 getMinimumTokenReserveRatio[_token] = _minimumReservesRatio;
369 isStrategyToken[_token] = true;
370:
413 /// @inheritdoc IBranchPort
414 function setCoreBranchRouter(address _coreBranchRouter, address _coreBranchBridgeAgent)
415 external
416 override
417 requiresCoreRouter
418 {
419 coreBranchRouterAddress = _coreBranchRouter;
420 isBridgeAgent[_coreBranchBridgeAgent] = true;
421 bridgeAgents.push(_coreBranchBridgeAgent);
422
423 emit CoreBranchSet(_coreBranchRouter, _coreBranchBridgeAgent);
424: }
When a type is downcast to a smaller type, the higher order bits are truncated, effectively applying a modulo to the original value. Without any other checks, this wrapping will lead to unexpected behavior and bugs
There are 8 instances of this issue:
File: src/BranchBridgeAgent.sol
/// @audit uint8
243: uint8(_dParams.hTokens.length),
/// @audit uint8
320: uint8(_dParams.hTokens.length),
/// @audit uint8
359: if (uint8(deposit.hTokens.length) == 1) {
/// @audit uint8
383: } else if (uint8(deposit.hTokens.length) > 1) {
/// @audit uint8
389: uint8(deposit.hTokens.length),
/// @audit uint8
400: uint8(deposit.hTokens.length),
GitHub: 243, 320, 359, 383, 389, 400
File: src/RootBridgeAgent.sol
/// @audit uint8
896: uint8(_hTokens.length),
/// @audit uint8
1092: uint8(hTokens.length),
If the length of the arrays are not required to be of the same length, user operations may not be fully executed due to a mismatch in the number of items iterated over, versus the number of items provided in the second array
There is one instance of this issue:
File: src/BranchPort.sol
246 function bridgeInMultiple(
247 address _recipient,
248 address[] memory _localAddresses,
249 address[] memory _underlyingAddresses,
250 uint256[] memory _amounts,
251 uint256[] memory _deposits
252: ) external override requiresBridgeAgent {
GitHub: 246
Having no access control on the function (e.g. require(msg.sender == address(weth))
) means that someone may send Ether to the contract, and have no way to get anything back out, which is a loss of funds. If the concern is having to spend a small amount of gas to check the sender against an immutable address, the code should at least have a function to rescue mistakenly-sent Ether.
There are 3 instances of this issue:
File: src/BranchBridgeAgent.sol
149: receive() external payable {}
GitHub: 149
File: src/RootBridgeAgent.sol
128: receive() external payable {}
GitHub: 128
File: src/VirtualAccount.sol
44: receive() external payable {}
GitHub: 44
Deprecated in favor of safeIncreaseAllowance()
and safeDecreaseAllowance()
. If only setting the initial allowance to the value that means infinite, safeIncreaseAllowance()
can be used instead. The function may currently work, but if a bug is found in this version of OpenZeppelin, and the version that you're forced to upgrade to no longer has this function, you'll encounter unnecessary delays in porting and testing replacement contracts.
There are 2 instances of this issue:
File: src/MulticallRootRouter.sol
521: outputToken.safeApprove(_bridgeAgentAddress, amountOut);
559: outputTokens[i].safeApprove(_bridgeAgentAddress, amountsOut[i]);
Ownable2Step
and Ownable2StepUpgradeable
prevent the contract ownership from mistakenly being transferred to an address that cannot handle it (e.g. due to a typo in the address), by requiring that the recipient of the owner permissions actively accept via a contract call of its own.
There are 12 instances of this issue:
see instances
File: src/BaseBranchRouter.sol
25: contract BaseBranchRouter is IBranchRouter, Ownable {
GitHub: 25
File: src/BranchBridgeAgentExecutor.sol
29: contract BranchBridgeAgentExecutor is Ownable, BridgeAgentConstants {
GitHub: 29
File: src/BranchPort.sol
17: contract BranchPort is Ownable, IBranchPort {
GitHub: 17
File: src/CoreRootRouter.sol
38 contract CoreRootRouter is IRootRouter, Ownable {
39 /*///////////////////////////////////////////////////////////////
40 CORE ROOT ROUTER STATE
41 //////////////////////////////////////////////////////////////*/
42
43: /// @notice Boolean to indicate if the contract is in set up mode.
GitHub: 38
File: src/MulticallRootRouter.sol
57: contract MulticallRootRouter is IRootRouter, Ownable {
GitHub: 57
File: src/RootBridgeAgentExecutor.sol
27 contract RootBridgeAgentExecutor is Ownable, BridgeAgentConstants {
28 /*///////////////////////////////////////////////////////////////
29 CONSTRUCTOR
30 //////////////////////////////////////////////////////////////*/
31 /**
32 * @notice Constructor for Root Bridge Agent Executor.
33 * @param _rootBridgeAgent the owner of the contract in charge of calling the different execution functions.
34 */
35 constructor(address _rootBridgeAgent) {
36: _initializeOwner(_rootBridgeAgent);
GitHub: 27
File: src/RootPort.sol
16: contract RootPort is Ownable, IRootPort {
GitHub: 16
File: src/factories/BranchBridgeAgentFactory.sol
19 contract BranchBridgeAgentFactory is Ownable, IBranchBridgeAgentFactory {
20: /// @notice Local Chain Id.
GitHub: 19
File: src/factories/ERC20hTokenBranchFactory.sol
12 contract ERC20hTokenBranchFactory is Ownable, IERC20hTokenBranchFactory {
13: /// @notice Local Network Identifier.
GitHub: 12
File: src/factories/ERC20hTokenRootFactory.sol
12 contract ERC20hTokenRootFactory is Ownable, IERC20hTokenRootFactory {
13: /// @notice Local Network Identifier.
GitHub: 12
File: src/token/ERC20hTokenBranch.sol
12 contract ERC20hTokenBranch is ERC20, Ownable, IERC20hTokenBranch {
13 constructor(
14 string memory chainName,
15 string memory chainSymbol,
16 string memory _name,
17 string memory _symbol,
18 uint8 _decimals,
19 address _owner
20 ) ERC20(string(string.concat(chainName, _name)), string(string.concat(chainSymbol, _symbol)), _decimals) {
21: _initializeOwner(_owner);
GitHub: 12
File: src/token/ERC20hTokenRoot.sol
12 contract ERC20hTokenRoot is ERC20, Ownable, IERC20hTokenRoot {
13: /// @inheritdoc IERC20hTokenRoot
GitHub: 12
If the intention is for Ether sent by a caller to be used for an actual purpose (i.e. the function is not just a WETH withdraw()
handler), the function should call another function (e.g. call weth.deposit()
and use the token on the caller's behalf) or at least emit an event to track that funds were sent directly to it.
There are 3 instances of this issue:
File: src/BranchBridgeAgent.sol
149: receive() external payable {}
GitHub: 149
File: src/RootBridgeAgent.sol
128: receive() external payable {}
GitHub: 128
File: src/VirtualAccount.sol
44: receive() external payable {}
GitHub: 44
Consider limiting the number of iterations in for-
loops that make external calls
There are 4 instances of this issue:
File: src/RootBridgeAgent.sol
328 IPort(localPortAddress).bridgeToRoot(
329 msg.sender,
330 IPort(localPortAddress).getGlobalTokenFromLocal(_hToken, _dstChainId),
331 settlement.amounts[i],
332 settlement.deposits[i],
333 _dstChainId
334: );
330: IPort(localPortAddress).getGlobalTokenFromLocal(_hToken, _dstChainId),
1072: hTokens[i] = IPort(localPortAddress).getLocalTokenFromGlobal(_globalAddresses[i], _dstChainId);
1073: tokens[i] = IPort(localPortAddress).getUnderlyingTokenFromLocal(hTokens[i], _dstChainId);
A copy-paste error or a typo may end up bricking protocol functionality, or sending tokens to an address with no known private key. Consider implementing a two-step procedure for updating protocol addresses, where the recipient is set as pending, and must 'accept' the assignment by making an affirmative call. A straight forward way of doing this would be to have the target contracts implement EIP-165, and to have the 'set' functions ensure that the recipient is of the right interface type.
There are 10 instances of this issue:
File: src/BranchPort.sol
331 function setCoreRouter(address _newCoreRouter) external override requiresCoreRouter {
332 require(coreBranchRouterAddress != address(0), "CoreRouter address is zero");
333 require(_newCoreRouter != address(0), "New CoreRouter address is zero");
334 coreBranchRouterAddress = _newCoreRouter;
335: }
362 function addStrategyToken(address _token, uint256 _minimumReservesRatio) external override requiresCoreRouter {
363 if (_minimumReservesRatio >= DIVISIONER || _minimumReservesRatio < MIN_RESERVE_RATIO) {
364 revert InvalidMinimumReservesRatio();
365 }
366
367 strategyTokens.push(_token);
368 getMinimumTokenReserveRatio[_token] = _minimumReservesRatio;
369 isStrategyToken[_token] = true;
370
371 emit StrategyTokenAdded(_token, _minimumReservesRatio);
372: }
382 function addPortStrategy(address _portStrategy, address _token, uint256 _dailyManagementLimit)
383 external
384 override
385 requiresCoreRouter
386 {
387 if (!isStrategyToken[_token]) revert UnrecognizedStrategyToken();
388 portStrategies.push(_portStrategy);
389 strategyDailyLimitAmount[_portStrategy][_token] = _dailyManagementLimit;
390 isPortStrategy[_portStrategy][_token] = true;
391
392 emit PortStrategyAdded(_portStrategy, _token, _dailyManagementLimit);
393: }
403 function updatePortStrategy(address _portStrategy, address _token, uint256 _dailyManagementLimit)
404 external
405 override
406 requiresCoreRouter
407 {
408 strategyDailyLimitAmount[_portStrategy][_token] = _dailyManagementLimit;
409
410 emit PortStrategyUpdated(_portStrategy, _token, _dailyManagementLimit);
411: }
414 function setCoreBranchRouter(address _coreBranchRouter, address _coreBranchBridgeAgent)
415 external
416 override
417 requiresCoreRouter
418 {
419 coreBranchRouterAddress = _coreBranchRouter;
420 isBridgeAgent[_coreBranchBridgeAgent] = true;
421 bridgeAgents.push(_coreBranchBridgeAgent);
422
423 emit CoreBranchSet(_coreBranchRouter, _coreBranchBridgeAgent);
424: }
GitHub: 331, 362, 382, 403, 414
File: src/RootPort.sol
239 function setAddresses(
240 address _globalAddress,
241 address _localAddress,
242 address _underlyingAddress,
243 uint256 _srcChainId
244 ) external override requiresCoreRootRouter {
245 if (_globalAddress == address(0)) revert InvalidGlobalAddress();
246 if (_localAddress == address(0)) revert InvalidLocalAddress();
247 if (_underlyingAddress == address(0)) revert InvalidUnderlyingAddress();
248
249 isGlobalAddress[_globalAddress] = true;
250 getGlobalTokenFromLocal[_localAddress][_srcChainId] = _globalAddress;
251 getLocalTokenFromGlobal[_globalAddress][_srcChainId] = _localAddress;
252 getLocalTokenFromUnderlying[_underlyingAddress][_srcChainId] = _localAddress;
253 getUnderlyingTokenFromLocal[_localAddress][_srcChainId] = _underlyingAddress;
254
255 emit LocalTokenAdded(_underlyingAddress, _localAddress, _globalAddress, _srcChainId);
256: }
259 function setLocalAddress(address _globalAddress, address _localAddress, uint256 _srcChainId)
260 external
261 override
262 requiresCoreRootRouter
263 {
264 if (_localAddress == address(0)) revert InvalidLocalAddress();
265
266 getGlobalTokenFromLocal[_localAddress][_srcChainId] = _globalAddress;
267 getLocalTokenFromGlobal[_globalAddress][_srcChainId] = _localAddress;
268
269 emit GlobalTokenAdded(_localAddress, _globalAddress, _srcChainId);
270: }
382 function addBridgeAgent(address _manager, address _bridgeAgent) external override requiresBridgeAgentFactory {
383 if (isBridgeAgent[_bridgeAgent]) revert AlreadyAddedBridgeAgent();
384
385 bridgeAgents.push(_bridgeAgent);
386 getBridgeAgentManager[_bridgeAgent] = _manager;
387 isBridgeAgent[_bridgeAgent] = true;
388
389 emit BridgeAgentAdded(_bridgeAgent, _manager);
390: }
483 function addEcosystemToken(address _ecoTokenGlobalAddress) external override onlyOwner {
484 // Check if token already added
485 if (isGlobalAddress[_ecoTokenGlobalAddress]) revert AlreadyAddedEcosystemToken();
486
487 // Check if token is already a underlying token in current chain
488 if (getUnderlyingTokenFromLocal[_ecoTokenGlobalAddress][localChainId] != address(0)) {
489 revert AlreadyAddedEcosystemToken();
490 }
491
492 // Check if token is already a local branch token in current chain
493 if (getLocalTokenFromUnderlying[_ecoTokenGlobalAddress][localChainId] != address(0)) {
494 revert AlreadyAddedEcosystemToken();
495 }
496
497 // Update State
498 // 1. Add new global token to global address mapping
499 isGlobalAddress[_ecoTokenGlobalAddress] = true;
500 // 2. Add new branch local token address to global token mapping
501 getGlobalTokenFromLocal[_ecoTokenGlobalAddress][localChainId] = _ecoTokenGlobalAddress;
502 // 3. Add new global token to branch local token address mapping
503 getLocalTokenFromGlobal[_ecoTokenGlobalAddress][localChainId] = _ecoTokenGlobalAddress;
504
505 emit EcosystemTokenAdded(_ecoTokenGlobalAddress);
506: }
509 function setCoreRootRouter(address _coreRootRouter, address _coreRootBridgeAgent) external override onlyOwner {
510 if (_coreRootRouter == address(0)) revert InvalidCoreRootRouter();
511 if (_coreRootBridgeAgent == address(0)) revert InvalidCoreRootBridgeAgent();
512
513 coreRootRouterAddress = _coreRootRouter;
514 coreRootBridgeAgentAddress = _coreRootBridgeAgent;
515 getBridgeAgentManager[_coreRootBridgeAgent] = owner();
516
517 emit CoreRootSet(_coreRootRouter, _coreRootBridgeAgent);
518: }
GitHub: 239, 259, 382, 483, 509
The name()
function is not a part of the ERC-20 standard, and was added later as an optional extension. As such, some valid ERC20 tokens do not support this interface, so it is unsafe to blindly cast all tokens to this interface, and then call this function.
There are 5 instances of this issue:
File: src/ArbitrumCoreBranchRouter.sol
56: string.concat("Arbitrum Ulysses ", ERC20(_underlyingAddress).name()),
GitHub: 56
File: src/CoreBranchRouter.sol
68: ERC20(_underlyingAddress).name(), ERC20(_underlyingAddress).symbol(), decimals, true
72: bytes memory params = abi.encode(_underlyingAddress, newToken, newToken.name(), newToken.symbol(), decimals);
File: src/CoreRootRouter.sol
426: ERC20(_globalAddress).name(),
GitHub: 426
File: src/factories/ERC20hTokenBranchFactory.sol
66: ERC20(_wrappedNativeTokenAddress).name(),
GitHub: 66
The symbol()
function is not a part of the ERC-20 standard, and was added later as an optional extension. As such, some valid ERC20 tokens do not support this interface, so it is unsafe to blindly cast all tokens to this interface, and then call this function.
There are 5 instances of this issue:
File: src/ArbitrumCoreBranchRouter.sol
57: string.concat("arb-u", ERC20(_underlyingAddress).symbol()),
GitHub: 57
File: src/CoreBranchRouter.sol
68: ERC20(_underlyingAddress).name(), ERC20(_underlyingAddress).symbol(), decimals, true
72: bytes memory params = abi.encode(_underlyingAddress, newToken, newToken.name(), newToken.symbol(), decimals);
File: src/CoreRootRouter.sol
427: ERC20(_globalAddress).symbol(),
GitHub: 427
File: src/factories/ERC20hTokenBranchFactory.sol
67: ERC20(_wrappedNativeTokenAddress).symbol(),
GitHub: 67
The decimals()
function is not a part of the ERC-20 standard, and was added later as an optional extension. As such, some valid ERC20 tokens do not support this interface, so it is unsafe to blindly cast all tokens to this interface, and then call this function.
There are 4 instances of this issue:
File: src/ArbitrumCoreBranchRouter.sol
58: ERC20(_underlyingAddress).decimals()
GitHub: 58
File: src/CoreBranchRouter.sol
64: uint8 decimals = ERC20(_underlyingAddress).decimals();
GitHub: 64
File: src/CoreRootRouter.sol
428: ERC20(_globalAddress).decimals(),
GitHub: 428
File: src/factories/ERC20hTokenBranchFactory.sol
68: ERC20(_wrappedNativeTokenAddress).decimals(),
GitHub: 68
SafeTransferLib.sol
has functions named similarly to functions that OpenZeppelin has, but they act differently. At the top of the file is the following comment:
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
This means that if one of the transfer functions is called on a contract that doesn't exist or that got selfdestructed, the call will succeede without any warning/revert, which may cause implicit token holdings validations to be ineffective. Consider using the OpenZeppelin version instead.
There are 2 instances of this issue:
File: src/ArbitrumBranchPort.sol
66: _underlyingAddress.safeTransferFrom(_depositor, address(this), _deposit);
128: _underlyingAddress.safeTransferFrom(_depositor, address(this), _deposit);
Even if the function follows the best practice of check-effects-interaction, not using a reentrancy guard when there may be transfer hooks will open the users of this protocol up to read-only reentrancies with no way to protect against it, except by block-listing the whole protocol.
There is one instance of this issue:
File: src/VirtualAccount.sol
/// @audit `withdrawERC721()`
62: ERC721(_token).transferFrom(address(this), msg.sender, _tokenId);
GitHub: 62
Calling approve()
without first calling approve(0)
if the current approval is non-zero will revert with some tokens, such as Tether (USDT). While Tether is known to do this, it applies to other tokens as well, which are trying to protect against this attack vector. safeApprove()
itself also implements this protection.
Always reset the approval to zero before changing it to a new value (SafeERC20.forceApprove()
does this for you), or use safeIncreaseAllowance()
/safeDecreaseAllowance()
There are 3 instances of this issue:
File: src/BaseBranchRouter.sol
175: ERC20(_token).approve(_localPortAddress, _deposit);
GitHub: 175
File: src/MulticallRootRouter.sol
521: outputToken.safeApprove(_bridgeAgentAddress, amountOut);
559: outputTokens[i].safeApprove(_bridgeAgentAddress, amountsOut[i]);
There is no limit specified on the amount of gas used, so the recipient can use up all of the transaction's gas, causing it to revert. Use addr.call{gas: <amount>}("")
or this library instead.
There are 8 instances of this issue:
File: src/BranchBridgeAgent.sol
/// @audit `_execute()`
717: (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata);
/// @audit `_execute()`
737: (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata);
File: src/RootBridgeAgent.sol
/// @audit `_execute()`
754: (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata);
/// @audit `_execute()`
779: (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata);
/// @audit `_performCall()`
835: callee.call{value: msg.value}("");
/// @audit `_performRetrySettlementCall()`
927: callee.call{value: _value}("");
File: src/VirtualAccount.sol
/// @audit `call()`
74: if (isContract(_call.target)) (success, returnData[i]) = _call.target.call(_call.callData);
/// @audit `payableCall()`
101: if (isContract(_call.target)) (success, returnData[i]) = _call.target.call{value: val}(_call.callData);
Low-level calls return success if there is no code present at the specified address. In addition to the zero-address checks, add a check to verify that <address>.code.length > 0
There are 4 instances of this issue:
File: src/ArbitrumCoreBranchRouter.sol
65 IBridgeAgent(localBridgeAgentAddress).callOutSystem(payable(msg.sender), payload, GasParams(0, 0));
66: }
118 IBridgeAgent(localBridgeAgentAddress).callOutSystem(payable(_refundee), payload, _gParams);
119: }
File: src/BaseBranchRouter.sol
84 IBridgeAgent(localBridgeAgentAddress).callOut{value: msg.value}(payable(msg.sender), _params, _gParams);
85: }
GitHub: 84
File: src/BranchBridgeAgent.sol
737 (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata);
738
739 //Update tx state if execution failed
740 if (!success) {
741 //Read the fallback flag and perform the fallback call if necessary. If not, allow for retrying deposit.
742: if (_hasFallbackToggled) {
GitHub: 737
Code should follow the best-practice of check-effects-interaction, where state variables are updated before any external calls are made. Doing so prevents a large class of reentrancy bugs.
There are 43 instances of this issue:
see instances
File: src/BaseBranchRouter.sol
/// @audit approve() called prior to this assignment
64: bridgeAgentExecutorAddress = IBridgeAgent(_localBridgeAgentAddress).bridgeAgentExecutorAddress();
GitHub: 64
File: src/BranchBridgeAgent.sol
/// @audit bridgeOut() called prior to this assignment
832: deposit.owner = _refundee;
/// @audit bridgeOut() called prior to this assignment
835: deposit.hTokens = addressArray;
/// @audit bridgeOut() called prior to this assignment
838: deposit.tokens = addressArray;
/// @audit bridgeOut() called prior to this assignment
841: deposit.amounts = uintArray;
/// @audit bridgeOut() called prior to this assignment
844: deposit.deposits = uintArray;
/// @audit bridgeOut() called prior to this assignment
846: deposit.status = STATUS_SUCCESS;
/// @audit bridgeOutMultiple() called prior to this assignment
882: deposit.owner = _refundee;
/// @audit bridgeOutMultiple() called prior to this assignment
883: deposit.hTokens = _hTokens;
/// @audit bridgeOutMultiple() called prior to this assignment
884: deposit.tokens = _tokens;
/// @audit bridgeOutMultiple() called prior to this assignment
885: deposit.amounts = _amounts;
/// @audit bridgeOutMultiple() called prior to this assignment
886: deposit.deposits = _deposits;
/// @audit bridgeOutMultiple() called prior to this assignment
887: deposit.status = STATUS_SUCCESS;
GitHub: 832, 835, 838, 841, 844, 846, 882, 883, 884, 885, 886, 887
File: src/BranchPort.sol
/// @audit withdraw() called prior to this assignment
205: getPortStrategyTokenDebt[_strategy][_token] = portStrategyTokenDebt - amountToWithdraw;
/// @audit withdraw() called prior to this assignment
207: getStrategyTokenDebt[_token] = strategyTokenDebt - amountToWithdraw;
File: src/CoreRootRouter.sol
/// @audit null() called prior to this assignment
88: hTokenFactoryAddress = _hTokenFactory;
GitHub: 88
File: src/RootBridgeAgent.sol
/// @audit bridgeToRoot() called prior to this assignment
254: settlementReference.status = STATUS_SUCCESS;
/// @audit bridgeToRoot() called prior to this assignment
343: delete getSettlement[_settlementNonce];
/// @audit bridgeToRoot() called prior to this assignment
680: settlementReference.status = STATUS_SUCCESS;
/// @audit bridgeToRoot() called prior to this assignment
1014: settlement.owner = _refundee;
/// @audit bridgeToRoot() called prior to this assignment
1015: settlement.recipient = _recipient;
/// @audit bridgeToRoot() called prior to this assignment
1018: settlement.hTokens = addressArray;
/// @audit bridgeToRoot() called prior to this assignment
1021: settlement.tokens = addressArray;
/// @audit bridgeToRoot() called prior to this assignment
1024: settlement.amounts = uintArray;
/// @audit bridgeToRoot() called prior to this assignment
1027: settlement.deposits = uintArray;
/// @audit bridgeToRoot() called prior to this assignment
1029: settlement.dstChainId = _dstChainId;
/// @audit bridgeToRoot() called prior to this assignment
1030: settlement.status = STATUS_SUCCESS;
/// @audit bridgeToRoot() called prior to this assignment
1106: settlement.owner = _refundee;
/// @audit bridgeToRoot() called prior to this assignment
1107: settlement.recipient = _recipient;
/// @audit bridgeToRoot() called prior to this assignment
1108: settlement.hTokens = hTokens;
/// @audit bridgeToRoot() called prior to this assignment
1109: settlement.tokens = tokens;
/// @audit bridgeToRoot() called prior to this assignment
1110: settlement.amounts = _amounts;
/// @audit bridgeToRoot() called prior to this assignment
1111: settlement.deposits = _deposits;
/// @audit bridgeToRoot() called prior to this assignment
1112: settlement.dstChainId = _dstChainId;
/// @audit bridgeToRoot() called prior to this assignment
1113: settlement.status = STATUS_SUCCESS;
GitHub: 254, 343, 680, 1014, 1015, 1018, 1021, 1024, 1027, 1029, 1030, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113
File: src/RootPort.sol
/// @audit syncBranchBridgeAgent() called prior to this assignment
162: getBridgeAgentManager[_coreRootBridgeAgent] = owner();
/// @audit syncBranchBridgeAgent() called prior to this assignment
465: isChainId[_chainId] = true;
/// @audit syncBranchBridgeAgent() called prior to this assignment
467: isGlobalAddress[newGlobalToken] = true;
/// @audit syncBranchBridgeAgent() called prior to this assignment
469: getGlobalTokenFromLocal[_newLocalBranchWrappedNativeTokenAddress][_chainId] = newGlobalToken;
/// @audit syncBranchBridgeAgent() called prior to this assignment
471: getLocalTokenFromGlobal[newGlobalToken][_chainId] = _newLocalBranchWrappedNativeTokenAddress;
/// @audit syncBranchBridgeAgent() called prior to this assignment
473 getLocalTokenFromUnderlying[_newUnderlyingBranchWrappedNativeTokenAddress][_chainId] =
474: _newLocalBranchWrappedNativeTokenAddress;
/// @audit syncBranchBridgeAgent() called prior to this assignment
476 getUnderlyingTokenFromLocal[_newLocalBranchWrappedNativeTokenAddress][_chainId] =
477: _newUnderlyingBranchWrappedNativeTokenAddress;
GitHub: 162, 465, 467, 469, 471, 473, 476
File: src/factories/ERC20hTokenBranchFactory.sol
/// @audit push() called prior to this assignment
74: localCoreRouterAddress = _coreRouter;
GitHub: 74
There are 7 instances of this issue:
File: src/CoreBranchRouter.sol
31: hTokenFactoryAddress = _hTokenFactoryAddress;
GitHub: 31
File: src/CoreRootRouter.sol
73: rootPortAddress = _rootPortAddress;
86: bridgeAgentAddress = payable(_bridgeAgentAddress);
88: hTokenFactoryAddress = _hTokenFactory;
File: src/VirtualAccount.sol
36: userAddress = _userAddress;
37: localPortAddress = _localPortAddress;
File: src/factories/RootBridgeAgentFactory.sol
35: lzEndpointAddress = _lzEndpointAddress;
GitHub: 35
There is one instance of this issue:
File: src/BranchPort.sol
419: coreBranchRouterAddress = _coreBranchRouter;
GitHub: 419
Consider adding minimum/maximum value checks to ensure that the state variables below can never be used to excessively harm users, including via griefing
There are 2 instances of this issue:
File: src/BranchPort.sol
389: strategyDailyLimitAmount[_portStrategy][_token] = _dailyManagementLimit;
408: strategyDailyLimitAmount[_portStrategy][_token] = _dailyManagementLimit;
Neither the listed functions, nor _mint()
prevent minting to address(0x0)
There are 2 instances of this issue:
File: src/token/ERC20hTokenBranch.sol
29 function mint(address account, uint256 amount) external override onlyOwner returns (bool) {
30 _mint(account, amount);
31 return true;
32: }
GitHub: 29
File: src/token/ERC20hTokenRoot.sol
57 function mint(address to, uint256 amount, uint256 chainId) external onlyOwner returns (bool) {
58 getTokenBalance[chainId] += amount;
59 _mint(to, amount);
60 return true;
61: }
GitHub: 57
The initialize()
functions below are not called by another contract atomically after the contract is deployed, so it's possible for a malicious user to call initialize()
which, if it's noticed in time, would require the project to re-deploy the contract in order to properly initialize. Consider creating a factory contract, which will new
and initialize()
each contract atomically.
There are 8 instances of this issue:
see instances
File: src/BaseBranchRouter.sol
60: function initialize(address _localBridgeAgentAddress) external onlyOwner {
GitHub: 60
File: src/BranchPort.sol
122: function initialize(address _coreBranchRouter, address _bridgeAgentFactory) external virtual onlyOwner {
GitHub: 122
File: src/CoreRootRouter.sol
83: function initialize(address _bridgeAgentAddress, address _hTokenFactory) external onlyOwner {
GitHub: 83
File: src/MulticallRootRouter.sol
109: function initialize(address _bridgeAgentAddress) external onlyOwner {
GitHub: 109
File: src/RootPort.sol
129: function initialize(address _bridgeAgentFactory, address _coreRootRouter) external onlyOwner {
GitHub: 129
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
56: function initialize(address _coreRootBridgeAgent) external override onlyOwner {
GitHub: 56
File: src/factories/ERC20hTokenBranchFactory.sol
60: function initialize(address _wrappedNativeTokenAddress, address _coreRouter) external onlyOwner {
GitHub: 60
File: src/factories/ERC20hTokenRootFactory.sol
49: function initialize(address _coreRouter) external onlyOwner {
GitHub: 49
Contracts are allowed to override their parents' functions and change the visibility from external
to public
.
There are 6 instances of this issue:
File: src/BranchBridgeAgent.sol
578: function lzReceive(uint16, bytes calldata _srcAddress, uint64, bytes calldata _payload) public override {
587 function lzReceiveNonBlocking(address _endpoint, bytes calldata _srcAddress, bytes calldata _payload)
588 public
589 override
590: requiresEndpoint(_endpoint, _srcAddress)
File: src/RootBridgeAgent.sol
423: function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64, bytes calldata _payload) public {
434 function lzReceiveNonBlocking(
435 address _endpoint,
436 uint16 _srcChainId,
437 bytes calldata _srcAddress,
438 bytes calldata _payload
439: ) public override requiresEndpoint(_endpoint, _srcChainId, _srcAddress) {
File: src/VirtualAccount.sol
85: function payableCall(PayableCall[] calldata calls) public payable returns (bytes[] memory returnData) {
GitHub: 85
File: src/token/ERC20hTokenBranch.sol
35: function burn(uint256 amount) public override onlyOwner {
GitHub: 35
Index event fields make the field more quickly accessible to off-chain tools that parse events. This is especially useful when it comes to filtering based on an address. However, note that each index field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (three fields). Where applicable, each event
should use three indexed
fields if there are three or more fields, and gas usage is not particularly of concern for the events in question. If there are fewer than three applicable fields, all of the applicable fields should be indexed.
There is one instance of this issue:
File: src/interfaces/IRootPort.sol
380: event VirtualAccountCreated(address indexed user, address account);
GitHub: 380
The compiler will inline the function, which will avoid JUMP
instructions usually associated with functions
There are 12 instances of this issue:
see instances
File: src/BranchBridgeAgent.sol
441: if (deposit.owner != msg.sender) revert NotDepositOwner();
624: if (executionState[nonce] != STATUS_READY) revert AlreadyExecutedTransaction();
File: src/BranchPort.sol
560: if (!isStrategyToken[_token]) revert UnrecognizedStrategyToken();
GitHub: 560
File: src/CoreRootRouter.sol
366: revert();
GitHub: 366
File: src/MulticallRootRouter.sol
204: revert();
GitHub: 204
File: src/RootBridgeAgent.sol
670: if (settlementReference.owner == address(0)) revert SettlementRetryUnavailable();
910: if (callee == address(0)) revert UnrecognizedBridgeAgent();
File: src/RootPort.sol
264: if (_localAddress == address(0)) revert InvalidLocalAddress();
299: if (!isGlobalAddress[_hToken]) revert UnrecognizedToken();
544: if (_coreBranchRouter == address(0)) revert InvalidCoreBranchRouter();
545: if (_coreBranchBridgeAgent == address(0)) revert InvalidCoreBrancBridgeAgent();
File: src/VirtualAccount.sol
103: if (!success) revert CallFailed();
GitHub: 103
The functions below have the same implementation as is seen in other files. The functions should be refactored into functions of a common base contract
There is one instance of this issue:
File: src/RootPort.sol
/// @audit seen in src/BranchPort.sol
166 function renounceOwnership() public payable override onlyOwner {
167 revert("Cannot renounce ownership");
168: }
GitHub: 166
Using import declarations of the form import {<identifier_name>} from "some/file.sol"
avoids polluting the symbol namespace making flattened files smaller, and speeds up compilation (but does not save any gas)
There is one instance of this issue:
File: src/interfaces/ILayerZeroEndpoint.sol
5: import "./ILayerZeroUserApplicationConfig.sol";
GitHub: 5
This should especially be done if the new value is not required to be different from the old value
There are 6 instances of this issue:
File: src/BranchPort.sol
/// @audit updatePortStrategy()
410: emit PortStrategyUpdated(_portStrategy, _token, _dailyManagementLimit);
/// @audit setCoreBranchRouter()
423: emit CoreBranchSet(_coreBranchRouter, _coreBranchBridgeAgent);
File: src/RootPort.sol
/// @audit setAddresses()
255: emit LocalTokenAdded(_underlyingAddress, _localAddress, _globalAddress, _srcChainId);
/// @audit setLocalAddress()
269: emit GlobalTokenAdded(_localAddress, _globalAddress, _srcChainId);
/// @audit setCoreRootRouter()
517: emit CoreRootSet(_coreRootRouter, _coreRootBridgeAgent);
/// @audit setCoreBranchRouter()
535: emit CoreBranchSet(_coreBranchRouter, _coreBranchBridgeAgent, _dstChainId);
Consider defining in only one contract so that values cannot become out of sync when only one location is updated. A cheap way to store constants in a single location is to create an internal constant
in a library
. If the variable is a local cache of another contract's value, consider making the cache variable internal or private, which will require external users to query the contract with the source of truth, so that callers don't get out of sync.
There are 25 instances of this issue:
see instances
File: src/BranchBridgeAgent.sol
/// @audit seen in src/ArbitrumBranchPort.sol
56: uint16 public immutable localChainId;
GitHub: 56
File: src/CoreRootRouter.sol
/// @audit seen in src/BranchBridgeAgent.sol
47: uint256 public immutable rootChainId;
/// @audit seen in src/ArbitrumBranchPort.sol
51: address public immutable rootPortAddress;
File: src/MulticallRootRouter.sol
/// @audit seen in src/BranchBridgeAgent.sol
65: uint256 public immutable localChainId;
/// @audit seen in src/BranchBridgeAgent.sol
68: address public immutable localPortAddress;
File: src/RootBridgeAgent.sol
/// @audit seen in src/MulticallRootRouter.sol
40: uint16 public immutable localChainId;
/// @audit seen in src/BranchBridgeAgent.sol
46: address public immutable localRouterAddress;
/// @audit seen in src/MulticallRootRouter.sol
49: address public immutable localPortAddress;
/// @audit seen in src/BranchBridgeAgent.sol
52: address public immutable lzEndpointAddress;
/// @audit seen in src/BranchBridgeAgent.sol
55: address public immutable bridgeAgentExecutorAddress;
File: src/RootPort.sol
/// @audit seen in src/RootBridgeAgent.sol
34: uint256 public immutable localChainId;
GitHub: 34
File: src/VirtualAccount.sol
/// @audit seen in src/RootBridgeAgent.sol
24: address public immutable override localPortAddress;
GitHub: 24
File: src/factories/BranchBridgeAgentFactory.sol
/// @audit seen in src/RootPort.sol
21: uint16 public immutable localChainId;
/// @audit seen in src/CoreRootRouter.sol
24: uint16 public immutable rootChainId;
/// @audit seen in src/VirtualAccount.sol
33: address public immutable localPortAddress;
/// @audit seen in src/RootBridgeAgent.sol
36: address public immutable lzEndpointAddress;
File: src/factories/ERC20hTokenBranchFactory.sol
/// @audit seen in src/factories/BranchBridgeAgentFactory.sol
14: uint24 public immutable localChainId;
/// @audit seen in src/factories/BranchBridgeAgentFactory.sol
17: address public immutable localPortAddress;
File: src/factories/ERC20hTokenRootFactory.sol
/// @audit seen in src/factories/ERC20hTokenBranchFactory.sol
14: uint16 public immutable localChainId;
/// @audit seen in src/CoreRootRouter.sol
17: address public immutable rootPortAddress;
File: src/factories/RootBridgeAgentFactory.sol
/// @audit seen in src/factories/BranchBridgeAgentFactory.sol
13: uint16 public immutable rootChainId;
/// @audit seen in src/factories/ERC20hTokenRootFactory.sol
16: address public immutable rootPortAddress;
/// @audit seen in src/factories/BranchBridgeAgentFactory.sol
19: address public immutable lzEndpointAddress;
File: src/token/ERC20hTokenRoot.sol
/// @audit seen in src/factories/ERC20hTokenRootFactory.sol
14: uint16 public immutable override localChainId;
/// @audit seen in src/RootBridgeAgent.sol
17: address public immutable override factoryAddress;
Some lines use // x
and some use //x
. The instances below point out the usages that don't follow the majority, within each file
There are 145 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
113: //Sends message to Root Bridge Agent
GitHub: 113
File: src/ArbitrumBranchPort.sol
49: ///@inheritdoc IArbitrumBranchPort
72: ///@inheritdoc IArbitrumBranchPort
126: //Store Underlying Tokens
131: //Burn hTokens if any are being used
File: src/ArbitrumCoreBranchRouter.sol
50: ///@inheritdoc CoreBranchRouter
52: //Encode Data, no need to create local token since we are already in the global environment
64: //Send Cross-Chain request (System Response/Request)
117: //Send Cross-Chain request
125: ///@inheritdoc CoreBranchRouter
File: src/BaseBranchRouter.sol
94: //Transfer tokens to this contract.
97: //Perform call to bridge agent.
109: //Transfer tokens to this contract.
112: //Perform call to bridge agent.
File: src/BranchBridgeAgent.sol
187: //Encode Data for cross-chain call.
190: //Perform Call
201: //Encode Data for cross-chain call.
204: //Perform Call
215: //Cache Deposit Nonce
218: //Encode Data for cross-chain call.
223: //Create Deposit and Send Cross-Chain request
226: //Perform Call
237: //Cache Deposit Nonce
240: //Encode Data for cross-chain call.
252: //Create Deposit and Send Cross-Chain request
257: //Perform Call
268: //Encode Data for cross-chain call.
271: //Perform Signed Call without deposit
283: //Cache Deposit Nonce
286: //Encode Data for cross-chain call.
298: //Create Deposit and Send Cross-Chain request
301: //Perform Call
334: //Perform Call
353: //Check if deposit belongs to message sender
356: //Encode Data for cross-chain call.
361: //Pack new Data
385: //Pack new Data
426: //Encode Data for cross-chain call.
429: //Update State and Perform Call
592: //Save Action Flag
603: //Check if tx has already been executed
606: //Try to execute the remote request
607: //Flag 0 - BranchBridgeAgentExecutor(bridgeAgentExecutorAddress).executeNoSettlement(localRouterAddress, _payload)
623: //Check if tx has already been executed
626: //Try to execute the remote request
627: //Flag 1 - BranchBridgeAgentExecutor(bridgeAgentExecutorAddress).executeWithSettlement(recipient, localRouterAddress, _payload)
645: //Check if tx has already been executed
648: //Try to execute remote request
662: //DEPOSIT FLAG: 3 (Retrieve Settlement)
667: //Get nonce
670: //Check if settlement is in retrieve mode
674: //Set settlement to retrieve mode, if not already set.
676: //Trigger fallback/Retry failed fallback
680: //DEPOSIT FLAG: 4 (Fallback)
682: //Get nonce
694: //Unrecognized Function Selector
713: //Update tx state as executed
716: //Try to execute the remote request
733: //Update tx state as executed
736: //Try to execute the remote request
739: //Update tx state if execution failed
741: //Read the fallback flag and perform the fallback call if necessary. If not, allow for retrying deposit.
769: //Sends message to LayerZero messaging layer
786: //Sends message to LayerZero messaging layer
937: //Verify Endpoint
941: //Verify Remote Caller
GitHub: 187, 190, 201, 204, 215, 218, 223, 226, 237, 240, 252, 257, 268, 271, 283, 286, 298, 301, 334, 353, 356, 361, 385, 426, 429, 592, 603, 606, 607, 623, 626, 627, 645, 648, 662, 667, 670, 674, 676, 680, 682, 694, 713, 716, 733, 736, 739, 741, 769, 786, 937, 941
File: src/CoreBranchRouter.sol
63: //Get Token Info
66: //Create Token
71: //Encode Data
77: //Send Cross-Chain request (System Response/Request)
174: //Create Token
183: //Send Cross-Chain request
231: //Send Cross-Chain request
GitHub: 63, 66, 71, 77, 174, 183, 231
File: src/CoreRootRouter.sol
138: //Add new global token to branch chain
173: //Add new global token to branch chain
192: //Encode CallData
198: //Add new global token to branch chain
225: //Add new global token to branch chain
256: //Add new global token to branch chain
286: //Add new global token to branch chain
436: //Add new global token to branch chain
465: //Create a new global token
GitHub: 138, 173, 192, 198, 225, 256, 286, 436, 465
File: src/MulticallRootRouter.sol
202: ///@inheritdoc IRootRouter
207: ///@inheritdoc IRootRouter
523: //Move output hTokens from Root to Branch and call 'clearToken'.
565: //Move output hTokens from Root to Branch and call 'clearTokens'.
File: src/RootBridgeAgent.sol
167: //Encode Data for call.
170: //Perform Call to clear hToken balance on destination branch chain.
197: //Perform Call.
275: //Get settlement storage reference
291: //Encode Data for cross-chain call.
294: //Retrieve Deposit
491: //Parse Deposit Nonce
494: //Check if tx has already been executed
543: //Check if tx has already been executed
576: //DEPOSIT FLAG: 5 (Call with Deposit + msg.sender)
581: //Check if tx has already been executed
679: //Update Settlement Staus
682: //Retry settlement call with new params and gas
700: //Parse deposit nonce
703: //Check if deposit is in retrieve mode
707: //Set settlement to retrieve mode, if not already set.
711: //Trigger fallback/Retry failed fallback
717: //DEPOSIT FLAG: 9 (Fallback)
750: //Update tx state as executed
753: //Try to execute the remote request
775: //Update tx state as executed
778: //Try to execute the remote request
781: //Update tx state if execution failed
783: //Read the fallback flag.
822: //Sends message to Layerzero Enpoint
834: //Send Gas to Local Branch Bridge Agent
836: //Execute locally
878: //Pack new Data
892: //Pack new Data
914: //Sends message to Layerzero Enpoint
926: //Send Gas to Local Branch Bridge Agent
928: //Execute locally
939: //Sends message to LayerZero messaging layer
986: //Update State to reflect bridgeOut
1063: //Update Settlement Nonce
GitHub: 167, 170, 197, 275, 291, 294, 491, 494, 543, 576, 581, 679, 682, 700, 703, 707, 711, 717, 750, 753, 775, 778, 781, 783, 822, 834, 836, 878, 892, 914, 926, 928, 939, 986, 1063
File: src/RootBridgeAgentExecutor.sol
87: // Read Deposit Params
96: // Bridge In Assets
99: // Check if there is additional calldata in the payload
133: // Check if there is additional calldata in the payload
184: // Check if there is additional calldata in the payload
218: // Check if there is additional calldata in the payload
272: // Parse Parameters
282: // Cache offset
285: // Parse Params
337: // Save Deposit Multiple Params
GitHub: 87, 96, 99, 133, 184, 218, 272, 282, 285, 337
File: src/interfaces/BridgeAgentStructs.sol
9: uint256 gasLimit; // gas allocated for the cross-chain call.
81: uint32 settlementNonce; // Settlement nonce.
82: address recipient; // Recipient of the settlement.
83: address hToken; // Input Local hTokens Address.
84: address token; // Input Native / underlying Token Address.
85: uint256 amount; // Amount of Local hTokens deposited for interaction.
86: uint256 deposit; // Amount of native tokens deposited for interaction.
90: uint8 numberOfAssets; // Number of assets to deposit.
91: address recipient; // Recipient of the settlement.
92: uint32 settlementNonce; // Settlement nonce.
93: address[] hTokens; // Input Local hTokens Addresses.
94: address[] tokens; // Input Native / underlying Token Addresses.
95: uint256[] amounts; // Amount of Local hTokens deposited for interaction.
96: uint256[] deposits; // Amount of native tokens deposited for interaction.
GitHub: 9, 81, 82, 83, 84, 85, 86, 90, 91, 92, 93, 94, 95, 96
Usually lines in source code are limited to 80 characters. Today's screens are much larger so it's reasonable to stretch this in some cases. The solidity style guide recommends a maximumum line length of 120 characters, so the lines below should be split when they reach that length.
There are 32 instances of this issue:
see instances
File: src/ArbitrumBranchPort.sol
60: address _globalToken = IRootPort(_rootPortAddress).getLocalTokenFromUnderlying(_underlyingAddress, localChainId);
GitHub: 60
File: src/BranchBridgeAgent.sol
112: * @param _lzEndpointAddress Local Layerzero Endpoint Address where cross-chain requests are sent to the Root Chain Router.
548: PARAMS_TKN_START + PARAMS_AMT_OFFSET * numOfAssets + PARAMS_ENTRY_SIZE * currentIterationOffset
607: //Flag 0 - BranchBridgeAgentExecutor(bridgeAgentExecutorAddress).executeNoSettlement(localRouterAddress, _payload)
627: //Flag 1 - BranchBridgeAgentExecutor(bridgeAgentExecutorAddress).executeWithSettlement(recipient, localRouterAddress, _payload)
649: // Flag 2 - BranchBridgeAgentExecutor(bridgeAgentExecutorAddress).executeWithSettlementMultiple(recipient, localRouterAddress, _payload)
763: * @param _gParams LayerZero gas information. (_gasLimit,_remoteBranchExecutionGas,_nativeTokenRecipientOnDstChain)
GitHub: 112, 548, 607, 627, 649, 763
File: src/BranchPort.sol
462: * @notice Internal function to return the minimum amount of reserves of a given Strategy Token the Port should hold.
GitHub: 462
File: src/MulticallRootRouter.sol
484: * @notice Function to perform a set of actions on the omnichain environment without using the user's Virtual Acccount.
603: /// @notice Verifies the caller is the Bridge Agent Executor. Internal function used in modifier to reduce contract bytesize.
File: src/RootBridgeAgent.sol
61: /// @notice Chain -> Branch Bridge Agent Address. For N chains, each Root Bridge Agent Address has M =< N Branch Bridge Agent Address.
64: /// @notice Message Path for each connected Branch Bridge Agent as bytes for Layzer Zero interaction = localAddress + destinationAddress abi.encodePacked()
84: /// @notice If true, bridge agent has already served a request with this nonce from a given chain. Chain -> Nonce -> Bool
457: // Flag 0 - RootBridgeAgentExecutor(bridgeAgentExecutorAddress).executeSystemRequest(_localRouterAddress, _payload, _srcChainId)
480: // Flag 1 - RootBridgeAgentExecutor(bridgeAgentExecutorAddress).executeNoDeposit(localRouterAddress, payload, _srcChainId)
503: // Flag 2 - RootBridgeAgentExecutor(bridgeAgentExecutorAddress).executeWithDeposit(localRouterAddress, _payload, _srcChainId)
526: // Flag 3 - RootBridgeAgentExecutor(bridgeAgentExecutorAddress).executeWithDepositMultiple(localRouterAddress, _payload, _srcChainId)
560: // Flag 4 - RootBridgeAgentExecutor(bridgeAgentExecutorAddress).executeSignedNoDeposit(address(userAccount), localRouterAddress, data, _srcChainId
598: // Flag 5 - RootBridgeAgentExecutor(bridgeAgentExecutorAddress).executeSignedWithDeposit(address(userAccount), localRouterAddress, data, _srcChainId)
638: // Flag 6 - RootBridgeAgentExecutor(bridgeAgentExecutorAddress).executeSignedWithDepositMultiple(address(userAccount), localRouterAddress, data, _srcChainId)
GitHub: 61, 64, 84, 457, 480, 503, 526, 560, 598, 638
File: src/VirtualAccount.sol
159: /// @notice Modifier that verifies msg sender is the approved to use the virtual account. Either the owner or an approved router.
GitHub: 159
File: src/interfaces/IBranchBridgeAgent.sol
36: * (See https://github.com/LayerZero-Labs/solidity-examples/blob/8e62ebc886407aafc89dbd2a778e61b7c0a25ca0/contracts/lzApp/NonblockingLzApp.sol)
GitHub: 36
File: src/interfaces/IBranchPort.sol
166: * @notice Reverts the toggle on the given bridge agent factory. If it's active, it will de-activate it and vice-versa.
GitHub: 166
File: src/interfaces/ILayerZeroEndpoint.sol
12: // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
14: // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
File: src/interfaces/IRootBridgeAgent.sol
34: * (See https://github.com/LayerZero-Labs/solidity-examples/blob/8e62ebc886407aafc89dbd2a778e61b7c0a25ca0/contracts/lzApp/NonblockingLzApp.sol)
178: * @param _refundee the effective owner of the settlement this address receives excess gas deposited on source chain
201: * @param _refundee the effective owner of the settlement this address receives excess gas deposited on source chain
File: src/interfaces/IRootRouter.sol
36: * @notice Function responsible of executing a crosschain request which contains cross-chain deposit information attached.
47: * @notice Function responsible of executing a crosschain request which contains cross-chain deposit information for multiple assets attached.
66: * @notice Function responsible of executing a crosschain request which contains cross-chain deposit information and msg.sender attached.
80: * @notice Function responsible of executing a crosschain request which contains cross-chain deposit information for multiple assets and msg.sender attached.
There are 13 instances of this issue:
File: src/BranchBridgeAgent.sol
/// @audit 77 lines (69 in the body)
343 function retryDeposit(
344 bool _isSigned,
345 uint32 _depositNonce,
346 bytes calldata _params,
347 GasParams calldata _gParams,
348 bool _hasFallbackToggled
349: ) external payable override lock {
/// @audit 78 lines (71 in the body)
494 function clearTokens(bytes calldata _sParams, address _recipient)
495 external
496 override
497 requiresAgentExecutor
498: returns (SettlementMultipleParams memory)
/// @audit 115 lines (109 in the body)
587 function lzReceiveNonBlocking(address _endpoint, bytes calldata _srcAddress, bytes calldata _payload)
588 public
589 override
590: requiresEndpoint(_endpoint, _srcAddress)
File: src/CoreBranchRouter.sol
/// @audit 64 lines (62 in the body)
86: function executeNoSettlement(bytes calldata _params) external payable virtual override requiresAgentExecutor {
GitHub: 86
File: src/MulticallRootRouter.sol
/// @audit 64 lines (62 in the body)
137: function execute(bytes calldata encodedData, uint16) external payable override lock requiresExecutor {
/// @audit 78 lines (70 in the body)
223 function executeSigned(bytes calldata encodedData, address userAccount, uint16)
224 external
225 payable
226 override
227 lock
228: requiresExecutor
/// @audit 78 lines (70 in the body)
312 function executeSignedDepositSingle(bytes calldata encodedData, DepositParams calldata, address userAccount, uint16)
313 external
314 payable
315 override
316 requiresExecutor
317: lock
/// @audit 77 lines (70 in the body)
401 function executeSignedDepositMultiple(
402 bytes calldata encodedData,
403 DepositMultipleParams calldata,
404 address userAccount,
405 uint16
406: ) external payable override requiresExecutor lock {
File: src/RootBridgeAgent.sol
/// @audit 304 lines (297 in the body)
434 function lzReceiveNonBlocking(
435 address _endpoint,
436 uint16 _srcChainId,
437 bytes calldata _srcAddress,
438 bytes calldata _payload
439: ) public override requiresEndpoint(_endpoint, _srcChainId, _srcAddress) {
/// @audit 76 lines (61 in the body)
856 function _performRetrySettlementCall(
857 bool _hasFallbackToggled,
858 address[] memory _hTokens,
859 address[] memory _tokens,
860 uint256[] memory _amounts,
861 uint256[] memory _deposits,
862 bytes memory _params,
863 uint32 _settlementNonce,
864 address payable _refundee,
865 address _recipient,
866 uint16 _dstChainId,
867 GasParams memory _gParams,
868: uint256 _value
/// @audit 66 lines (54 in the body)
966 function _createSettlement(
967 uint32 _settlementNonce,
968 address payable _refundee,
969 address _recipient,
970 uint16 _dstChainId,
971 bytes memory _params,
972 address _globalAddress,
973 uint256 _amount,
974 uint256 _deposit,
975 bool _hasFallbackToggled
976: ) internal returns (bytes memory _payload) {
/// @audit 70 lines (58 in the body)
1045 function _createSettlementMultiple(
1046 uint32 _settlementNonce,
1047 address payable _refundee,
1048 address _recipient,
1049 uint16 _dstChainId,
1050 address[] memory _globalAddresses,
1051 uint256[] memory _amounts,
1052 uint256[] memory _deposits,
1053 bytes memory _params,
1054 bool _hasFallbackToggled
1055: ) internal returns (bytes memory _payload) {
File: src/RootBridgeAgentExecutor.sol
/// @audit 81 lines (76 in the body)
268 function _bridgeInMultiple(address _recipient, bytes calldata _dParams, uint16 _srcChainId)
269 internal
270: returns (DepositMultipleParams memory dParams)
GitHub: 268
Some files use >=
, some use ^
. The instances below are examples of the method that has the fewest instances for a specific version. Note that using >=
without also specifying <=
will lead to failures to compile, or external project incompatability, when the major version changes and there are breaking-changes, so ^
should be preferred regardless of the instance counts
There are 3 instances of this issue:
File: src/interfaces/ILayerZeroEndpoint.sol
3: pragma solidity >=0.5.0;
GitHub: 3
File: src/interfaces/ILayerZeroReceiver.sol
3: pragma solidity >=0.5.0;
GitHub: 3
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
3: pragma solidity >=0.5.0;
GitHub: 3
There will be breaking changes in future versions of solidity, and at that point your code will no longer be compatable. While you may have the specific version to use in a configuration file, others that include your source files may not.
There are 3 instances of this issue:
File: src/interfaces/ILayerZeroEndpoint.sol
3: pragma solidity >=0.5.0;
GitHub: 3
File: src/interfaces/ILayerZeroReceiver.sol
3: pragma solidity >=0.5.0;
GitHub: 3
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
3: pragma solidity >=0.5.0;
GitHub: 3
There are 37 instances of this issue:
see instances
File: src/BranchBridgeAgent.sol
/// @audit Enpoint
929: /// @notice Modifier verifies the caller is the Layerzero Enpoint or Local Branch Bridge Agent.
GitHub: 929
File: src/BranchBridgeAgentExecutor.sol
/// @audit reamininig
91: // Send reamininig native / gas token to recipient
/// @audit reamininig
125: // Send reamininig native / gas token to recipient
File: src/BranchPort.sol
/// @audit overrriden
134: /// @notice Function being overrriden to prevent mistakenly renouncing ownership.
/// @audit startegy
177: // Withdraw tokens from startegy
/// @audit startegy
209: // Withdraw tokens from startegy
File: src/MulticallRootRouter.sol
/// @audit Acccount
484: * @notice Function to perform a set of actions on the omnichain environment without using the user's Virtual Acccount.
/// @audit adn
501: * @param refundee settlement owner adn excess gas receiver.
/// @audit adn
537: * @param refundee settlement owner adn excess gas receiver.
File: src/RootBridgeAgent.sol
/// @audit Layzer
64: /// @notice Message Path for each connected Branch Bridge Agent as bytes for Layzer Zero interaction = localAddress + destinationAddress abi.encodePacked()
/// @audit setttlement
300: // Get setttlement storage reference
/// @audit Staus
679: //Update Settlement Staus
/// @audit Enpoint
822: //Sends message to Layerzero Enpoint
/// @audit mulitple
890: // Check if it's mulitple asset settlement
/// @audit Enpoint
914: //Sends message to Layerzero Enpoint
/// @audit Enpoint
934: * @notice Internal function performs call to Layerzero Enpoint Contract for cross-chain messaging.
/// @audit Setttlement
1013: // Update Setttlement
/// @audit Setttlement
1105: // Update Setttlement
/// @audit Enpoint
1203: /// @notice Modifier verifies the caller is the Layerzero Enpoint or Local Branch Bridge Agent.
GitHub: 64, 300, 679, 822, 890, 914, 934, 1013, 1105, 1203
File: src/RootPort.sol
/// @audit overriden
165: /// @notice Function being overriden to prevent mistakenly renouncing ownership.
GitHub: 165
File: src/factories/RootBridgeAgentFactory.sol
/// @audit Enpoint
18: /// @notice Local Layerzero Enpoint Address
GitHub: 18
File: src/interfaces/BridgeAgentConstants.sol
/// @audit Redeeem
19: // Settlement / Deposit Redeeem Status
GitHub: 19
File: src/interfaces/IBranchBridgeAgent.sol
/// @audit Enpoint
130: * @notice Internal function performs call to Layerzero Enpoint Contract for cross-chain messaging.
/// @audit enconded
145: * @param params enconded parameters to execute on the root chain router.
/// @audit enconded
157: * @param params enconded parameters to execute on the root chain router.
/// @audit enconded
173: * @param params enconded parameters to execute on the root chain router.
/// @audit enconded
189: * @param params enconded parameters to execute on the root chain router.
/// @audit enconded
201: * @param params enconded parameters to execute on the root chain router.
/// @audit enconded
220: * @param params enconded parameters to execute on the root chain router.
/// @audit addresse
299: * @param hToken local hToken addresse to clear balance for.
/// @audit addresse
300: * @param token native / underlying token addresse to clear balance for.
GitHub: 130, 145, 157, 173, 189, 201, 220, 299, 300
File: src/interfaces/IBranchPort.sol
/// @audit Ulyses
8: * @notice Ulyses `Port` implementation for Branch Chain deployment. This contract
/// @audit thfe
172: * @notice Reverts thfe toggle on the given bridge agent If it's active, it will de-activate it and vice-versa.
File: src/interfaces/IBranchRouter.sol
/// @audit enconded
41: * @param params RLP enconded parameters to execute on the root chain.
GitHub: 41
File: src/interfaces/IRootBridgeAgent.sol
/// @audit singned
50: * 0x04 | Call to Root Router without Deposit + singned message.
/// @audit singned
51: * 0x05 | Call to Root Router with Deposit + singned message.
/// @audit foricng
245: * @notice Function that allows retrieval of failed Settlement's foricng fallback to be triggered.
There are 3 instances of this issue:
File: src/interfaces/BridgeAgentStructs.sol
GitHub: various
File: src/interfaces/IMulticall2.sol
GitHub: various
File: src/token/ERC20hTokenBranch.sol
GitHub: various
See this link for an explanation of the correct ordering
There are 2 instances of this issue:
File: src/BranchBridgeAgent.sol
/// @audit function lzReceiveNonBlocking() public override requiresEndpoint() { //Save Action Flag bytes1 flag = _payload[0] & 0x7F; // Save settlement nonce uint32 nonce; // DEPOSIT FLAG: 0 () if () { // Get Settlement Nonce nonce = uint32()); //Check if tx has already been executed if () revert AlreadyExecutedTransaction(); //Try to execute the remote request //Flag 0 - BranchBridgeAgentExecutor().executeNoSettlement() _execute() ); // DEPOSIT FLAG: 1 () } else if () { // Parse recipient address payable recipient = payable()))); // Parse Settlement Nonce nonce = uint32()); //Check if tx has already been executed if () revert AlreadyExecutedTransaction(); //Try to execute the remote request //Flag 1 - BranchBridgeAgentExecutor().executeWithSettlement() _execute() ); // DEPOSIT FLAG: 2 () } else if () { // Parse recipient address payable recipient = payable()))); // Parse deposit nonce nonce = uint32()); //Check if tx has already been executed if () revert AlreadyExecutedTransaction(); //Try to execute remote request // Flag 2 - BranchBridgeAgentExecutor().executeWithSettlementMultiple() _execute() ); //DEPOSIT FLAG: 3 () } else if () { // Parse recipient address payable recipient = payable()))); //Get nonce nonce = uint32()); //Check if settlement is in retrieve mode if () { revert AlreadyExecutedTransaction(); } else { //Set settlement to retrieve mode, if not already set. if () executionState[nonce] = STATUS_RETRIEVE; //Trigger fallback/Retry failed fallback _performFallbackCall(); } //DEPOSIT FLAG: 4 () } else if () { //Get nonce nonce = uint32()); // Reopen Deposit for redemption getDeposit[nonce].status = STATUS_FAILED; // Emit Fallback Event emit LogFallback(); // Return to prevent unnecessary logic/emits return; //Unrecognized Function Selector } else { revert UnknownFlag(); } // Emit Execution Event emit LogExecute(); } : override before constant/payable
587 function lzReceiveNonBlocking(address _endpoint, bytes calldata _srcAddress, bytes calldata _payload)
588 public
589 override
590: requiresEndpoint(_endpoint, _srcAddress)
GitHub: 587
File: src/RootBridgeAgent.sol
/// @audit function redeemSettlement() external override lock { // Get setttlement storage reference Settlement storage settlement = getSettlement[_settlementNonce]; // Get deposit owner. address settlementOwner = settlement.owner; // Check if Settlement is redeemable. if () revert SettlementRedeemUnavailable(); if ()) revert SettlementRedeemUnavailable(); // Check if Settlement Owner is msg.sender or msg.sender is the virtual account of the settlement owner. if () { if ().getUserAccount())) { revert NotSettlementOwner(); } } // Clear Global hTokens To Recipient on Root Chain cancelling Settlement to Branch for () { // Save to memory address _hToken = settlement.hTokens[i]; // Check if asset if ()) { // Save to memory uint24 _dstChainId = settlement.dstChainId; // Move hTokens from Branch to Root + Mint Sufficient hTokens to match new port deposit IPort().bridgeToRoot().getGlobalTokenFromLocal(), settlement.amounts[i], settlement.deposits[i], _dstChainId ); } unchecked { ++i; } } // Delete Settlement delete getSettlement[_settlementNonce]; } : override before virtual
299: function redeemSettlement(uint32 _settlementNonce) external override lock {
GitHub: 299
Assembly blocks take a lot more time to audit than normal Solidity code, and often have gotchas and side-effects that the Solidity versions of the same code do not. Consider adding more comments explaining what is being done in every step of the assembly code, and describe why assembly is being used instead of Solidity.
There is one instance of this issue:
File: src/VirtualAccount.sol
149 assembly {
150 size := extcodesize(addr)
151: }
GitHub: 149
There are 3 instances of this issue:
File: src/BranchPort.sol
83 mapping(address strategy => mapping(address token => uint256 dailyLimitRemaining)) public
84: strategyDailyLimitRemaining;
GitHub: 83
File: src/RootPort.sol
96 mapping(address chainId => mapping(uint256 underlyingAddress => address localAddress)) public
97: getLocalTokenFromUnderlying;
100 mapping(address chainId => mapping(uint256 localAddress => address underlyingAddress)) public
101: getUnderlyingTokenFromLocal;
According to the Solidity style guide, functions should be laid out in the following order :constructor()
, receive()
, fallback()
, external
, public
, internal
, private
, but the cases below do not follow this pattern
There are 11 instances of this issue:
File: src/ArbitrumCoreBranchRouter.sol
/// @audit _receiveAddBridgeAgent() came earlier
126: function executeNoSettlement(bytes calldata _data) external payable override requiresAgentExecutor {
GitHub: 126
File: src/BranchBridgeAgent.sol
/// @audit _execute() came earlier
765: function _performCall(address payable _refundee, bytes memory _payload, GasParams calldata _gParams)
GitHub: 765
File: src/BranchPort.sol
/// @audit renounceOwnership() came earlier
144: function manage(address _token, uint256 _amount) external override requiresPortStrategy(_token) {
/// @audit withdraw() came earlier
237 function bridgeIn(address _recipient, address _localAddress, uint256 _amount)
238 external
239 override
240: requiresBridgeAgent
File: src/RootBridgeAgent.sol
/// @audit bridgeIn() came earlier
387 function bridgeInMultiple(address _recipient, DepositMultipleParams calldata _dParams, uint256 _srcChainId)
388 external
389 override
390: requiresAgentExecutor
/// @audit _execute() came earlier
808 function _performCall(
809 uint16 _dstChainId,
810 address payable _refundee,
811 bytes memory _payload,
812: GasParams calldata _gParams
/// @audit _updateStateOnBridgeOut() came earlier
1170: function approveBranchBridgeAgent(uint256 _branchChainId) external override requiresManager {
File: src/RootPort.sol
/// @audit renounceOwnership() came earlier
175 function getLocalToken(address _localAddress, uint256 _srcChainId, uint256 _dstChainId)
176 external
177 view
178 override
179: returns (address)
/// @audit _getLocalToken() came earlier
200 function getUnderlyingTokenFromGlobal(address _globalAddress, uint256 _srcChainId)
201 external
202 view
203 override
204: returns (address)
/// @audit addVirtualAccount() came earlier
369 function toggleVirtualAccountApproved(VirtualAccount _userAccount, address _router)
370 external
371 override
372: requiresBridgeAgent
File: src/VirtualAccount.sol
/// @audit payableCall() came earlier
119: function onERC721Received(address, address, uint256, bytes calldata) external pure override returns (bytes4) {
GitHub: 119
The style guide says that, within a contract, the ordering should be 1) Type declarations, 2) State variables, 3) Events, 4) Modifiers, and 5) Functions, but the contract(s) below do not follow this ordering
There are 15 instances of this issue:
see instances
File: src/BaseBranchRouter.sol
/// @audit function _transferAndApproveMultipleTokens came earlier
206 modifier requiresAgentExecutor() {
207 if (msg.sender != bridgeAgentExecutorAddress) revert UnrecognizedBridgeAgentExecutor();
208 _;
209: }
GitHub: 206
File: src/BranchBridgeAgent.sol
/// @audit function _clearToken came earlier
922 modifier lock() {
923 require(_unlocked == 1);
924 _unlocked = 2;
925 _;
926 _unlocked = 1;
927: }
/// @audit function _requiresEndpoint came earlier
947 modifier requiresRouter() {
948 if (msg.sender != localRouterAddress) revert UnrecognizedRouter();
949 _;
950: }
File: src/BranchPort.sol
/// @audit function _bridgeOut came earlier
541 modifier requiresCoreRouter() {
542 if (msg.sender != coreBranchRouterAddress) revert UnrecognizedCore();
543 _;
544: }
GitHub: 541
File: src/CoreRootRouter.sol
/// @audit function _syncBranchBridgeAgent came earlier
511 modifier requiresExecutor() {
512 if (msg.sender != bridgeAgentExecutorAddress) revert UnrecognizedBridgeAgentExecutor();
513 _;
514: }
GitHub: 511
File: src/MulticallRootRouter.sol
/// @audit function _decode came earlier
590 modifier lock() {
591 require(_unlocked == 1);
592 _unlocked = 2;
593 _;
594 _unlocked = 1;
595: }
GitHub: 590
File: src/RootBridgeAgent.sol
/// @audit function syncBranchBridgeAgent came earlier
1190 modifier lock() {
1191 require(_unlocked == 1);
1192 _unlocked = 2;
1193 _;
1194 _unlocked = 1;
1195: }
GitHub: 1190
File: src/RootPort.sol
/// @audit function syncNewCoreBranchRouter came earlier
557 modifier requiresBridgeAgentFactory() {
558 if (!isBridgeAgentFactory[msg.sender]) revert UnrecognizedBridgeAgentFactory();
559 _;
560: }
GitHub: 557
File: src/VirtualAccount.sol
/// @audit function isContract came earlier
160 modifier requiresApprovedCaller() {
161 if (!IRootPort(localPortAddress).isRouterApproved(this, msg.sender)) {
162 if (msg.sender != userAddress) {
163 revert UnauthorizedCaller();
164 }
165 }
166 _;
167: }
GitHub: 160
File: src/factories/ERC20hTokenBranchFactory.sol
/// @audit function createToken came earlier
112 modifier requiresCoreRouter() {
113 if (msg.sender != localCoreRouterAddress) revert UnrecognizedCoreRouter();
114 _;
115: }
GitHub: 112
File: src/factories/ERC20hTokenRootFactory.sol
/// @audit function createToken came earlier
96 modifier requiresCoreRouterOrPort() {
97 if (msg.sender != coreRootRouterAddress) {
98 if (msg.sender != rootPortAddress) {
99 revert UnrecognizedCoreRouterOrPort();
100 }
101 }
102 _;
103: }
GitHub: 96
File: src/interfaces/IBranchBridgeAgent.sol
/// @audit function lzReceiveNonBlocking came earlier
332: event LogExecute(uint256 indexed nonce);
GitHub: 332
File: src/interfaces/IBranchPort.sol
/// @audit function setCoreBranchRouter came earlier
220: event DebtCreated(address indexed _strategy, address indexed _token, uint256 _amount);
GitHub: 220
File: src/interfaces/IRootBridgeAgent.sol
/// @audit function syncBranchBridgeAgent came earlier
337: event LogExecute(uint256 indexed depositNonce, uint256 indexed srcChainId);
GitHub: 337
File: src/interfaces/IRootPort.sol
/// @audit function syncNewCoreBranchRouter came earlier
371: event BridgeAgentFactoryAdded(address indexed bridgeAgentFactory);
GitHub: 371
function foo(address x, address)
-> function foo(address x, address /* y */)
There are 18 instances of this issue:
File: src/ArbitrumBranchBridgeAgent.sol
88 /// @dev This functionality should be accessed from Root environment
89: function retrySettlement(uint32, bytes calldata, GasParams[2] calldata, bool) external payable override lock {}
GitHub: 88
File: src/BranchBridgeAgent.sol
578: function lzReceive(uint16, bytes calldata _srcAddress, uint64, bytes calldata _payload) public override {
GitHub: 578
File: src/CoreRootRouter.sol
332: function execute(bytes calldata _encodedData, uint16) external payable override requiresExecutor {
350: function executeDepositSingle(bytes memory, DepositParams memory, uint16)
360: function executeDepositMultiple(bytes calldata, DepositMultipleParams memory, uint16)
370: function executeSigned(bytes memory, address, uint16) external payable override requiresExecutor {
375: function executeSignedDepositSingle(bytes memory, DepositParams memory, address, uint16)
385: function executeSignedDepositMultiple(bytes memory, DepositMultipleParams memory, address, uint16)
GitHub: 332, 350, 360, 370, 375, 385
File: src/MulticallRootRouter.sol
122 /// @dev This function will revert when called.
123: function executeResponse(bytes memory, uint16) external payable override {
137: function execute(bytes calldata encodedData, uint16) external payable override lock requiresExecutor {
203: function executeDepositSingle(bytes calldata, DepositParams calldata, uint16) external payable override {
209: function executeDepositMultiple(bytes calldata, DepositMultipleParams calldata, uint16) external payable {
223: function executeSigned(bytes calldata encodedData, address userAccount, uint16)
312: function executeSignedDepositSingle(bytes calldata encodedData, DepositParams calldata, address userAccount, uint16)
GitHub: 122, 137, 203, 209, 223, 312
File: src/RootBridgeAgent.sol
423: function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64, bytes calldata _payload) public {
GitHub: 423
File: src/VirtualAccount.sol
119: function onERC721Received(address, address, uint256, bytes calldata) external pure override returns (bytes4) {
124: function onERC1155Received(address, address, uint256, uint256, bytes calldata)
134: function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata)
NatSpec must begin with ///
, or use /* ... */
syntax
There are 67 instances of this issue:
File: src/interfaces/ILayerZeroEndpoint.sol
8: // @notice send a LayerZero message to the specified address at a LayerZero endpoint.
9: // @param _dstChainId - the destination chain identifier
10: // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
11: // @param _payload - a custom bytes payload to send to the destination contract
12: // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
13: // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
14: // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
24: // @notice used by the messaging library to publish verified payload
25: // @param _srcChainId - the source chain identifier
26: // @param _srcAddress - the source contract (as bytes) at the source chain
27: // @param _dstAddress - the address on destination chain
28: // @param _nonce - the unbound message ordering nonce
29: // @param _gasLimit - the gas limit for external contract execution
30: // @param _payload - verified payload to send to the destination contract
40: // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain
41: // @param _srcChainId - the source chain identifier
42: // @param _srcAddress - the source chain contract address
45: // @notice get the outboundNonce from this source chain which, consequently, is always an EVM
46: // @param _srcAddress - the source chain contract address
49: // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery
50: // @param _dstChainId - the destination chain identifier
51: // @param _userApplication - the user app address on this EVM chain
52: // @param _payload - the custom message to send over LayerZero
53: // @param _payInZRO - if false, user app pays the protocol fee in native token
54: // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain
63: // @notice get this Endpoint's immutable source identifier
66: // @notice the interface to retry failed message on this Endpoint destination
67: // @param _srcChainId - the source chain identifier
68: // @param _srcAddress - the source chain contract address
69: // @param _payload - the payload to be retried
72: // @notice query if any STORED payload (message blocking) at the endpoint.
73: // @param _srcChainId - the source chain identifier
74: // @param _srcAddress - the source chain contract address
77: // @notice query if the _libraryAddress is valid for sending msgs.
78: // @param _userApplication - the user app address on this EVM chain
81: // @notice query if the _libraryAddress is valid for receiving msgs.
82: // @param _userApplication - the user app address on this EVM chain
85: // @notice query if the non-reentrancy guard for send() is on
86: // @return true if the guard is on. false otherwise
89: // @notice query if the non-reentrancy guard for receive() is on
90: // @return true if the guard is on. false otherwise
93: // @notice get the configuration of the LayerZero messaging library of the specified version
94: // @param _version - messaging library version
95: // @param _chainId - the chainId for the pending config change
96: // @param _userApplication - the contract address of the user application
97: // @param _configType - type of configuration. every messaging library has its own convention.
103: // @notice get the send() LayerZero messaging library version
104: // @param _userApplication - the contract address of the user application
107: // @notice get the lzReceive() LayerZero messaging library version
108: // @param _userApplication - the contract address of the user application
GitHub: 8, 9, 10, 11, 12, 13, 14, 24, 25, 26, 27, 28, 29, 30, 40, 41, 42, 45, 46, 49, 50, 51, 52, 53, 54, 63, 66, 67, 68, 69, 72, 73, 74, 77, 78, 81, 82, 85, 86, 89, 90, 93, 94, 95, 96, 97, 103, 104, 107, 108
File: src/interfaces/ILayerZeroReceiver.sol
6: // @notice LayerZero endpoint will invoke this function to deliver the message on the destination
7: // @param _srcChainId - the source endpoint identifier
8: // @param _srcAddress - the source sending contract address from the source chain
9: // @param _nonce - the ordered message nonce
10: // @param _payload - the signed payload is the UA bytes has encoded to be sent
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
6: // @notice set the configuration of the LayerZero messaging library of the specified version
7: // @param _version - messaging library version
8: // @param _chainId - the chainId for the pending config change
9: // @param _configType - type of configuration. every messaging library has its own convention.
10: // @param _config - configuration in the bytes. can encode arbitrary content.
13: // @notice set the send() LayerZero messaging library version to _version
14: // @param _version - new messaging library version
17: // @notice set the lzReceive() LayerZero messaging library version to _version
18: // @param _version - new messaging library version
21: // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload
22: // @param _srcChainId - the chainId of the source chain
23: // @param _srcAddress - the contract address of the source contract at the source chain
GitHub: 6, 7, 8, 9, 10, 13, 14, 17, 18, 21, 22, 23
While 100% code coverage does not guarantee that there are no bugs, it often will catch easy-to-find bugs, and will ensure that there are fewer regressions when the code invariably has to be modified. Furthermore, in order to get full coverage, code authors will often have to re-organize their code so that it is more modular, so that each component can be tested separately, which reduces interdependencies between modules and layers, and makes for code that is easier to reason about and audit.
There is one instance of this issue:
File: Various Files
Large code bases, or code with lots of inline-assembly, complicated math, or complicated interactions between multiple contracts, should implement invariant fuzzing tests. Invariant fuzzers such as Echidna require the test writer to come up with invariants which should not be violated under any circumstances, and the fuzzer tests various inputs and function calls to ensure that the invariants always hold. Even code with 100% code coverage can still have bugs due to the order of the operations a user performs, and invariant fuzzers, with properly and extensively-written invariants, can close this testing gap significantly.
There is one instance of this issue:
File: Various Files
Consider using formal verification to mathematically prove that your code does what is intended, and does not have any edge cases with unexpected behavior. The solidity compiler itself has this functionality built in
There is one instance of this issue:
File: Various Files
[N‑25] Multiple address
/ID mappings can be combined into a single mapping
of an address
/ID to a struct
, for readability
Well-organized data structures make code reviews easier, which may lead to fewer bugs. Consider combining related mappings into mappings to structs, so it's clear what data is related
There are 3 instances of this issue:
File: src/BranchPort.sol
74 mapping(address strategy => mapping(address token => uint256 debt)) public getPortStrategyTokenDebt;
75
76 /// @notice Mapping returns the last time a given Port Strategy managed a given Strategy Token.
77 mapping(address strategy => mapping(address token => uint256 lastManaged)) public lastManaged;
78
79 /// @notice Mapping returns the time limit a given Port Strategy must wait before managing a Strategy Token.
80 mapping(address strategy => mapping(address token => uint256 dailyLimitAmount)) public strategyDailyLimitAmount;
81
82 /// @notice Mapping returns the amount of a Strategy Token a given Port Strategy can manage.
83 mapping(address strategy => mapping(address token => uint256 dailyLimitRemaining)) public
84: strategyDailyLimitRemaining;
GitHub: 74
File: src/RootBridgeAgent.sol
62 mapping(uint256 chainId => address branchBridgeAgent) public getBranchBridgeAgent;
63
64 /// @notice Message Path for each connected Branch Bridge Agent as bytes for Layzer Zero interaction = localAddress + destinationAddress abi.encodePacked()
65 mapping(uint256 chainId => bytes branchBridgeAgentPath) public getBranchBridgeAgentPath;
66
67 /// @notice If true, bridge agent manager has allowed for a new given branch bridge agent to be synced/added.
68: mapping(uint256 chainId => bool allowed) public isBranchBridgeAgentAllowed;
GitHub: 62
File: src/RootPort.sol
87 mapping(address token => bool isGlobalToken) public isGlobalAddress;
88
89 /// @notice ChainId -> Local Address -> Global Address
90 mapping(address chainId => mapping(uint256 localAddress => address globalAddress)) public getGlobalTokenFromLocal;
91
92 /// @notice ChainId -> Global Address -> Local Address
93 mapping(address chainId => mapping(uint256 globalAddress => address localAddress)) public getLocalTokenFromGlobal;
94
95 /// @notice ChainId -> Underlying Address -> Local Address
96 mapping(address chainId => mapping(uint256 underlyingAddress => address localAddress)) public
97 getLocalTokenFromUnderlying;
98
99 /// @notice Mapping from Local Address to Underlying Address.
100 mapping(address chainId => mapping(uint256 localAddress => address underlyingAddress)) public
101: getUnderlyingTokenFromLocal;
GitHub: 87
Custom errors are available from solidity version 0.8.4. Custom errors are more easily processed in try
-catch
blocks, and are easier to re-use and maintain.
There are 54 instances of this issue:
see instances
File: src/ArbitrumBranchPort.sol
39: require(_rootPortAddress != address(0), "Root Port Address cannot be 0");
GitHub: 39
File: src/BaseBranchRouter.sol
61: require(_localBridgeAgentAddress != address(0), "Bridge Agent address cannot be 0");
213: require(_unlocked == 1);
File: src/BranchBridgeAgent.sol
125: require(_rootBridgeAgentAddress != address(0), "Root Bridge Agent Address cannot be the zero address.");
126 require(
127 _lzEndpointAddress != address(0) || _rootChainId == _localChainId,
128 "Layerzero Endpoint Address cannot be the zero address."
129: );
130: require(_localRouterAddress != address(0), "Local Router Address cannot be the zero address.");
131: require(_localPortAddress != address(0), "Local Port Address cannot be the zero address.");
923: require(_unlocked == 1);
GitHub: 125, 126, 130, 131, 923
File: src/BranchPort.sol
109: require(_owner != address(0), "Owner is zero address");
123: require(coreBranchRouterAddress == address(0), "Contract already initialized");
124: require(!isBridgeAgentFactory[_bridgeAgentFactory], "Contract already initialized");
126: require(_coreBranchRouter != address(0), "CoreBranchRouter is zero address");
127: require(_bridgeAgentFactory != address(0), "BridgeAgentFactory is zero address");
181: require(ERC20(_token).balanceOf(address(this)) - currBalance == _amount, "Port Strategy Withdraw Failed");
213 require(
214 ERC20(_token).balanceOf(address(this)) - currBalance == amountToWithdraw, "Port Strategy Withdraw Failed"
215: );
332: require(coreBranchRouterAddress != address(0), "CoreRouter address is zero");
333: require(_newCoreRouter != address(0), "New CoreRouter address is zero");
567: require(_unlocked == 1);
GitHub: 109, 123, 124, 126, 127, 181, 213, 332, 333, 567
File: src/CoreRootRouter.sol
84: require(_setup, "Contract is already initialized");
278: require(msg.sender == rootPortAddress, "Only root port can call");
File: src/MulticallRootRouter.sol
93: require(_localPortAddress != address(0), "Local Port Address cannot be 0");
94: require(_multicallAddress != address(0), "Multicall Address cannot be 0");
110: require(_bridgeAgentAddress != address(0), "Bridge Agent Address cannot be 0");
591: require(_unlocked == 1);
File: src/RootBridgeAgent.sol
111: require(_lzEndpointAddress != address(0), "Layerzero Enpoint Address cannot be zero address");
112: require(_localPortAddress != address(0), "Port Address cannot be zero address");
113: require(_localRouterAddress != address(0), "Router Address cannot be zero address");
1191: require(_unlocked == 1);
File: src/RootPort.sol
130: require(_bridgeAgentFactory != address(0), "Bridge Agent Factory cannot be 0 address.");
131: require(_coreRootRouter != address(0), "Core Root Router cannot be 0 address.");
132: require(_setup, "Setup ended.");
152: require(_coreRootBridgeAgent != address(0), "Core Root Bridge Agent cannot be 0 address.");
153: require(_coreLocalBranchBridgeAgent != address(0), "Core Local Branch Bridge Agent cannot be 0 address.");
154: require(_localBranchPortAddress != address(0), "Local Branch Port Address cannot be 0 address.");
155: require(isBridgeAgent[_coreRootBridgeAgent], "Core Bridge Agent doesn't exist.");
156: require(_setupCore, "Core Setup ended.");
GitHub: 130, 131, 132, 152, 153, 154, 155, 156
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
57: require(_coreRootBridgeAgent != address(0), "Core Root Bridge Agent Address cannot be 0");
84 require(
85 msg.sender == localCoreBranchRouterAddress, "Only the Core Branch Router can create a new Bridge Agent."
86: );
87 require(
88 _rootBridgeAgentFactoryAddress == rootBridgeAgentFactoryAddress,
89 "Root Bridge Agent Factory Address does not match."
90: );
File: src/factories/BranchBridgeAgentFactory.sol
61: require(_rootBridgeAgentFactoryAddress != address(0), "Root Bridge Agent Factory Address cannot be 0");
62 require(
63 _lzEndpointAddress != address(0) || _rootChainId == _localChainId,
64 "Layerzero Endpoint Address cannot be the zero address."
65: );
66: require(_localCoreBranchRouterAddress != address(0), "Core Branch Router Address cannot be 0");
67: require(_localPortAddress != address(0), "Port Address cannot be 0");
68: require(_owner != address(0), "Owner cannot be 0");
88: require(_coreRootBridgeAgent != address(0), "Core Root Bridge Agent cannot be 0");
120 require(
121 msg.sender == localCoreBranchRouterAddress, "Only the Core Branch Router can create a new Bridge Agent."
122: );
123 require(
124 _rootBridgeAgentFactoryAddress == rootBridgeAgentFactoryAddress,
125 "Root Bridge Agent Factory Address does not match."
126: );
GitHub: 61, 62, 66, 67, 68, 88, 120, 123
File: src/factories/ERC20hTokenBranchFactory.sol
43: require(_localPortAddress != address(0), "Port address cannot be 0");
61: require(_coreRouter != address(0), "CoreRouter address cannot be 0");
File: src/factories/ERC20hTokenRootFactory.sol
35: require(_rootPortAddress != address(0), "Root Port Address cannot be 0");
50: require(_coreRouter != address(0), "CoreRouter address cannot be 0");
File: src/factories/RootBridgeAgentFactory.sol
32: require(_rootPortAddress != address(0), "Root Port Address cannot be 0");
GitHub: 32
File: src/token/ERC20hTokenRoot.sol
39: require(_rootPortAddress != address(0), "Root Port Address cannot be 0");
40: require(_factoryAddress != address(0), "Factory Address cannot be 0");
abi.encodeCall()
has compiler type safety, whereas the other two functions do not
There are 12 instances of this issue:
File: src/BranchBridgeAgent.sol
582: abi.encodeWithSelector(this.lzReceiveNonBlocking.selector, msg.sender, _srcAddress, _payload)
654: abi.encodeWithSelector(
632: abi.encodeWithSelector(
610: abi.encodeWithSelector(
File: src/RootBridgeAgent.sol
427: abi.encodeWithSelector(this.lzReceiveNonBlocking.selector, msg.sender, _srcChainId, _srcAddress, _payload)
643: abi.encodeWithSelector(
603: abi.encodeWithSelector(
563: abi.encodeWithSelector(
529: abi.encodeWithSelector(
506: abi.encodeWithSelector(
483: abi.encodeWithSelector(
460: abi.encodeWithSelector(
GitHub: 427, 643, 603, 563, 529, 506, 483, 460
According to the Solidity Style Guide, non-external
/public
variable names should begin with an underscore
There are 23 instances of this issue:
File: src/BranchBridgeAgent.sol
64: bytes private rootBridgeAgentPath;
GitHub: 64
File: src/BranchPort.sol
97: uint256 internal constant DIVISIONER = 1e4;
98: uint256 internal constant MIN_RESERVE_RATIO = 3e3;
File: src/interfaces/BridgeAgentConstants.sol
13: uint8 internal constant STATUS_READY = 0;
15: uint8 internal constant STATUS_DONE = 1;
17: uint8 internal constant STATUS_RETRIEVE = 2;
21: uint8 internal constant STATUS_FAILED = 1;
23: uint8 internal constant STATUS_SUCCESS = 0;
27: uint256 internal constant PARAMS_START = 1;
29: uint256 internal constant PARAMS_START_SIGNED = 21;
31: uint256 internal constant PARAMS_TKN_START = 5;
33: uint256 internal constant PARAMS_TKN_START_SIGNED = 25;
35: uint256 internal constant PARAMS_ENTRY_SIZE = 32;
37: uint256 internal constant PARAMS_ADDRESS_SIZE = 20;
39: uint256 internal constant PARAMS_TKN_SET_SIZE = 109;
41: uint256 internal constant PARAMS_TKN_SET_SIZE_MULTIPLE = 128;
43: uint256 internal constant ADDRESS_END_OFFSET = 12;
45: uint256 internal constant PARAMS_AMT_OFFSET = 64;
47: uint256 internal constant PARAMS_DEPOSIT_OFFSET = 96;
49: uint256 internal constant PARAMS_END_OFFSET = 6;
51: uint256 internal constant PARAMS_END_SIGNED_OFFSET = 26;
53: uint256 internal constant PARAMS_SETTLEMENT_OFFSET = 129;
57: uint256 internal constant MAX_TOKENS_LENGTH = 255;
GitHub: 13, 15, 17, 21, 23, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 57
For immutable
variable names, each word should use all capital letters, with underscores separating each word (CONSTANT_CASE)
There are 39 instances of this issue:
see instances
File: src/ArbitrumBranchPort.sol
22: uint16 public immutable localChainId;
26: address public immutable rootPortAddress;
File: src/BranchBridgeAgent.sol
53: uint16 public immutable rootChainId;
56: uint16 public immutable localChainId;
60: address public immutable rootBridgeAgentAddress;
67: address public immutable lzEndpointAddress;
70: address public immutable localRouterAddress;
74: address public immutable localPortAddress;
77: address public immutable bridgeAgentExecutorAddress;
GitHub: 53, 56, 60, 67, 70, 74, 77
File: src/CoreBranchRouter.sol
20: address public immutable hTokenFactoryAddress;
GitHub: 20
File: src/CoreRootRouter.sol
47: uint256 public immutable rootChainId;
51: address public immutable rootPortAddress;
File: src/MulticallRootRouter.sol
65: uint256 public immutable localChainId;
68: address public immutable localPortAddress;
71: address public immutable multicallAddress;
File: src/RootBridgeAgent.sol
40: uint16 public immutable localChainId;
43: address public immutable factoryAddress;
46: address public immutable localRouterAddress;
49: address public immutable localPortAddress;
52: address public immutable lzEndpointAddress;
55: address public immutable bridgeAgentExecutorAddress;
GitHub: 40, 43, 46, 49, 52, 55
File: src/RootPort.sol
34: uint256 public immutable localChainId;
GitHub: 34
File: src/VirtualAccount.sol
21: address public immutable override userAddress;
24: address public immutable override localPortAddress;
File: src/factories/BranchBridgeAgentFactory.sol
21: uint16 public immutable localChainId;
24: uint16 public immutable rootChainId;
27: address public immutable rootBridgeAgentFactoryAddress;
30: address public immutable localCoreBranchRouterAddress;
33: address public immutable localPortAddress;
36: address public immutable lzEndpointAddress;
GitHub: 21, 24, 27, 30, 33, 36
File: src/factories/ERC20hTokenBranchFactory.sol
14: uint24 public immutable localChainId;
17: address public immutable localPortAddress;
File: src/factories/ERC20hTokenRootFactory.sol
14: uint16 public immutable localChainId;
17: address public immutable rootPortAddress;
File: src/factories/RootBridgeAgentFactory.sol
13: uint16 public immutable rootChainId;
16: address public immutable rootPortAddress;
19: address public immutable lzEndpointAddress;
File: src/token/ERC20hTokenRoot.sol
14: uint16 public immutable override localChainId;
17: address public immutable override factoryAddress;
There are 66 instances of this issue:
see instances
File: src/ArbitrumCoreBranchRouter.sol
127: if (_data[0] == 0x02) {
146: } else if (_data[0] == 0x03) {
152: } else if (_data[0] == 0x04) {
157: } else if (_data[0] == 0x05) {
162: } else if (_data[0] == 0x06) {
GitHub: 127, 146, 152, 157, 162
File: src/BranchBridgeAgent.sol
376: deposit.hTokens[0],
377: deposit.tokens[0],
378: deposit.amounts[0],
379: deposit.deposits[0],
366: deposit.hTokens[0],
367: deposit.tokens[0],
368: deposit.amounts[0],
369: deposit.deposits[0],
471: bytes memory params = abi.encode(_settlementNonce, msg.sender, _params, _gParams[1]);
477: _performCall(payable(msg.sender), payload, _gParams[0]);
501: uint8 numOfAssets = uint8(bytes1(_sParams[0]));
593: bytes1 flag = _payload[0] & 0x7F;
651: _payload[0] == 0x82,
629: _payload[0] == 0x81,
834: addressArray[0] = _hToken;
837: addressArray[0] = _token;
840: uintArray[0] = _amount;
843: uintArray[0] = _deposit;
GitHub: 376, 377, 378, 379, 366, 367, 368, 369, 471, 477, 501, 593, 651, 629, 834, 837, 840, 843
File: src/CoreBranchRouter.sol
48: bytes memory params = abi.encode(msg.sender, _globalAddress, _dstChainId, [_gParams[1], _gParams[2]]);
54: IBridgeAgent(localBridgeAgentAddress).callOut{value: msg.value}(payable(msg.sender), payload, _gParams[0]);
88: if (_params[0] == 0x01) {
100: } else if (_params[0] == 0x02) {
115: } else if (_params[0] == 0x03) {
121: } else if (_params[0] == 0x04) {
127: } else if (_params[0] == 0x05) {
133: } else if (_params[0] == 0x06) {
140: } else if (_params[0] == 0x07) {
GitHub: 48, 48, 54, 88, 100, 115, 121, 127, 133, 140
File: src/CoreRootRouter.sol
132: _gParams[1]
140: payable(_refundee), _refundee, _dstChainId, payload, _gParams[0]
304: bytes1 funcId = _encodedData[0];
334: bytes1 funcId = _encodedData[0];
339: abi.decode(_encodedData[1:], (address, address, uint16, GasParams[2]));
430: _gParams[1]
438: payable(_refundee), _refundee, _dstChainId, payload, _gParams[0]
GitHub: 132, 140, 304, 334, 339, 430, 438
File: src/MulticallRootRouter.sol
139: bytes1 funcId = encodedData[0];
231: bytes1 funcId = encodedData[0];
320: bytes1 funcId = encodedData[0];
408: bytes1 funcId = encodedData[0];
File: src/RootBridgeAgent.sol
444: if (_payload[0] == 0x00) {
467: } else if (_payload[0] == 0x01) {
490: } else if (_payload[0] == 0x02) {
513: } else if (_payload[0] == 0x03) {
539: } else if (_payload[0] == 0x04) {
577: } else if (_payload[0] & 0x7F == 0x05) {
617: } else if (_payload[0] & 0x7F == 0x06) {
657: } else if (_payload[0] & 0x7F == 0x07) {
699: } else if (_payload[0] == 0x08) {
718: } else if (_payload[0] == 0x09) {
684: _payload[0] == 0x87,
640: _payload[0] == 0x86,
600: _payload[0] == 0x85,
883: _hTokens[0],
884: _tokens[0],
885: _amounts[0],
886: _deposits[0],
1017: addressArray[0] = localAddress;
1020: addressArray[0] = underlyingAddress;
1023: uintArray[0] = _amount;
1026: uintArray[0] = _deposit;
GitHub: 444, 467, 490, 513, 539, 577, 617, 657, 699, 718, 684, 640, 600, 883, 884, 885, 886, 1017, 1020, 1023, 1026
File: src/RootBridgeAgentExecutor.sol
273: uint8 numOfAssets = uint8(bytes1(_dParams[0]));
GitHub: 273
Consider moving to solidity version 0.8.18 or later, and using named mappings to make it easier to understand the purpose of each mapping
There are 40 instances of this issue:
File: src/BranchBridgeAgent.sol
87: mapping(uint256 depositNonce => Deposit depositInfo) public getDeposit;
94: mapping(uint256 settlementNonce => uint256 state) public executionState;
File: src/BranchPort.sol
32: mapping(address bridgeAgent => bool isActiveBridgeAgent) public isBridgeAgent;
42: mapping(address bridgeAgentFactory => bool isActiveBridgeAgentFactory) public isBridgeAgentFactory;
52: mapping(address token => bool allowsStrategies) public isStrategyToken;
58: mapping(address token => uint256 debt) public getStrategyTokenDebt;
61: mapping(address token => uint256 minimumReserveRatio) public getMinimumTokenReserveRatio;
68: mapping(address strategy => mapping(address token => bool isActiveStrategy)) public isPortStrategy;
74: mapping(address strategy => mapping(address token => uint256 debt)) public getPortStrategyTokenDebt;
77: mapping(address strategy => mapping(address token => uint256 lastManaged)) public lastManaged;
80: mapping(address strategy => mapping(address token => uint256 dailyLimitAmount)) public strategyDailyLimitAmount;
83: mapping(address strategy => mapping(address token => uint256 dailyLimitRemaining)) public
GitHub: 32, 42, 52, 58, 61, 68, 68, 74, 74, 77, 77, 80, 80, 83, 83
File: src/RootBridgeAgent.sol
62: mapping(uint256 chainId => address branchBridgeAgent) public getBranchBridgeAgent;
65: mapping(uint256 chainId => bytes branchBridgeAgentPath) public getBranchBridgeAgentPath;
68: mapping(uint256 chainId => bool allowed) public isBranchBridgeAgentAllowed;
78: mapping(uint256 nonce => Settlement settlementInfo) public getSettlement;
85: mapping(uint256 chainId => mapping(uint256 nonce => uint256 state)) public executionState;
GitHub: 62, 65, 68, 78, 85, 85
File: src/RootPort.sol
50: mapping(address user => VirtualAccount account) public getUserAccount;
54: mapping(VirtualAccount acount => mapping(address router => bool allowed)) public isRouterApproved;
61: mapping(uint256 chainId => bool isActive) public isChainId;
64: mapping(address bridgeAgent => bool isActive) public isBridgeAgent;
70: mapping(address bridgeAgent => address bridgeAgentManager) public getBridgeAgentManager;
77: mapping(address bridgeAgentFactory => bool isActive) public isBridgeAgentFactory;
87: mapping(address token => bool isGlobalToken) public isGlobalAddress;
90: mapping(address chainId => mapping(uint256 localAddress => address globalAddress)) public getGlobalTokenFromLocal;
93: mapping(address chainId => mapping(uint256 globalAddress => address localAddress)) public getLocalTokenFromGlobal;
96: mapping(address chainId => mapping(uint256 underlyingAddress => address localAddress)) public
100: mapping(address chainId => mapping(uint256 localAddress => address underlyingAddress)) public
GitHub: 50, 54, 54, 61, 64, 70, 77, 87, 90, 90, 93, 93, 96, 96, 100, 100
File: src/token/ERC20hTokenRoot.sol
20: mapping(uint256 chainId => uint256 balance) public override getTokenBalance;
GitHub: 20
Starting with Solidity version 0.8.8, using the override
keyword when the function solely overrides an interface function, and the function doesn't exist in multiple base contracts, is unnecessary.
There are 117 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
89: function retrySettlement(uint32, bytes calldata, GasParams[2] calldata, bool) external payable override lock {}
99: function _performCall(address payable, bytes memory _calldata, GasParams calldata) internal override {
112: function _performFallbackCall(address payable, uint32 _settlementNonce) internal override {
125: function _requiresEndpoint(address _endpoint, bytes calldata) internal view override {
File: src/ArbitrumBranchPort.sol
50 function depositToPort(address _depositor, address _recipient, address _underlyingAddress, uint256 _deposit)
51 external
52 override
53 lock
54 requiresBridgeAgent
55: {
73 function withdrawFromPort(address _depositor, address _recipient, address _globalAddress, uint256 _amount)
74 external
75 override
76 lock
77 requiresBridgeAgent
78: {
107: function _bridgeIn(address _recipient, address _localAddress, uint256 _amount) internal override {
119 function _bridgeOut(
120 address _depositor,
121 address _localAddress,
122 address _underlyingAddress,
123 uint256 _amount,
124 uint256 _deposit
125: ) internal override {
File: src/ArbitrumCoreBranchRouter.sol
51: function addLocalToken(address _underlyingAddress, GasParams calldata) external payable override {
85 function _receiveAddBridgeAgent(
86 address _newBranchRouter,
87 address _branchBridgeAgentFactory,
88 address _rootBridgeAgent,
89 address _rootBridgeAgentFactory,
90 address _refundee,
91 GasParams memory _gParams
92: ) internal override {
126: function executeNoSettlement(bytes calldata _data) external payable override requiresAgentExecutor {
File: src/BaseBranchRouter.sol
74: function getDepositEntry(uint32 _depositNonce) external view override returns (Deposit memory) {
83: function callOut(bytes calldata _params, GasParams calldata _gParams) external payable override lock {
88 function callOutAndBridge(bytes calldata _params, DepositInput calldata _dParams, GasParams calldata _gParams)
89 external
90 payable
91 override
92 lock
93: {
104 function callOutAndBridgeMultiple(
105 bytes calldata _params,
106 DepositMultipleInput calldata _dParams,
107 GasParams calldata _gParams
108: ) external payable override lock {
123: function executeNoSettlement(bytes calldata) external payable virtual override requiresAgentExecutor {
128 function executeSettlement(bytes calldata, SettlementParams memory)
129 external
130 payable
131 virtual
132 override
133 requiresAgentExecutor
134: {
139 function executeSettlementMultiple(bytes calldata, SettlementMultipleParams memory)
140 external
141 payable
142 virtual
143 override
144 requiresAgentExecutor
145: {
GitHub: 74, 83, 88, 104, 123, 128, 139
File: src/BranchBridgeAgent.sol
156: function getDepositEntry(uint32 _depositNonce) external view override returns (Deposit memory) {
180 function callOutSystem(address payable _refundee, bytes calldata _params, GasParams calldata _gParams)
181 external
182 payable
183 override
184 lock
185 requiresRouter
186: {
195 function callOut(address payable _refundee, bytes calldata _params, GasParams calldata _gParams)
196 external
197 payable
198 override
199 lock
200: {
209 function callOutAndBridge(
210 address payable _refundee,
211 bytes calldata _params,
212 DepositInput memory _dParams,
213 GasParams calldata _gParams
214: ) external payable override lock {
231 function callOutAndBridgeMultiple(
232 address payable _refundee,
233 bytes calldata _params,
234 DepositMultipleInput memory _dParams,
235 GasParams calldata _gParams
236: ) external payable override lock {
262 function callOutSigned(address payable _refundee, bytes calldata _params, GasParams calldata _gParams)
263 external
264 payable
265 override
266 lock
267: {
276 function callOutSignedAndBridge(
277 address payable _refundee,
278 bytes calldata _params,
279 DepositInput memory _dParams,
280 GasParams calldata _gParams,
281 bool _hasFallbackToggled
282: ) external payable override lock {
306 function callOutSignedAndBridgeMultiple(
307 address payable _refundee,
308 bytes calldata _params,
309 DepositMultipleInput memory _dParams,
310 GasParams calldata _gParams,
311 bool _hasFallbackToggled
312: ) external payable override lock {
343 function retryDeposit(
344 bool _isSigned,
345 uint32 _depositNonce,
346 bytes calldata _params,
347 GasParams calldata _gParams,
348 bool _hasFallbackToggled
349: ) external payable override lock {
422: function retrieveDeposit(uint32 _depositNonce, GasParams calldata _gParams) external payable override lock {
434: function redeemDeposit(uint32 _depositNonce) external override lock {
464 function retrySettlement(
465 uint32 _settlementNonce,
466 bytes calldata _params,
467 GasParams[2] calldata _gParams,
468 bool _hasFallbackToggled
469: ) external payable virtual override lock {
485 function clearToken(address _recipient, address _hToken, address _token, uint256 _amount, uint256 _deposit)
486 external
487 override
488 requiresAgentExecutor
489: {
494 function clearTokens(bytes calldata _sParams, address _recipient)
495 external
496 override
497 requiresAgentExecutor
498 returns (SettlementMultipleParams memory)
499: {
578: function lzReceive(uint16, bytes calldata _srcAddress, uint64, bytes calldata _payload) public override {
587 function lzReceiveNonBlocking(address _endpoint, bytes calldata _srcAddress, bytes calldata _payload)
588 public
589 override
590 requiresEndpoint(_endpoint, _srcAddress)
591: {
GitHub: 156, 180, 195, 209, 231, 262, 276, 306, 343, 422, 434, 464, 485, 494, 578, 587
File: src/BranchPort.sol
135: function renounceOwnership() public payable override onlyOwner {
144: function manage(address _token, uint256 _amount) external override requiresPortStrategy(_token) {
167: function replenishReserves(address _token, uint256 _amount) external override lock {
188: function replenishReserves(address _strategy, address _token) external override lock {
226 function withdraw(address _recipient, address _underlyingAddress, uint256 _deposit)
227 public
228 virtual
229 override
230 lock
231 requiresBridgeAgent
232: {
237 function bridgeIn(address _recipient, address _localAddress, uint256 _amount)
238 external
239 override
240 requiresBridgeAgent
241: {
246 function bridgeInMultiple(
247 address _recipient,
248 address[] memory _localAddresses,
249 address[] memory _underlyingAddresses,
250 uint256[] memory _amounts,
251 uint256[] memory _deposits
252: ) external override requiresBridgeAgent {
277 function bridgeOut(
278 address _depositor,
279 address _localAddress,
280 address _underlyingAddress,
281 uint256 _amount,
282 uint256 _deposit
283: ) external override lock requiresBridgeAgent {
288 function bridgeOutMultiple(
289 address _depositor,
290 address[] memory _localAddresses,
291 address[] memory _underlyingAddresses,
292 uint256[] memory _amounts,
293 uint256[] memory _deposits
294: ) external override lock requiresBridgeAgent {
319: function addBridgeAgent(address _bridgeAgent) external override requiresBridgeAgentFactory {
331: function setCoreRouter(address _newCoreRouter) external override requiresCoreRouter {
338: function addBridgeAgentFactory(address _newBridgeAgentFactory) external override requiresCoreRouter {
348: function toggleBridgeAgentFactory(address _newBridgeAgentFactory) external override requiresCoreRouter {
355: function toggleBridgeAgent(address _bridgeAgent) external override requiresCoreRouter {
362: function addStrategyToken(address _token, uint256 _minimumReservesRatio) external override requiresCoreRouter {
375: function toggleStrategyToken(address _token) external override requiresCoreRouter {
382 function addPortStrategy(address _portStrategy, address _token, uint256 _dailyManagementLimit)
383 external
384 override
385 requiresCoreRouter
386: {
396: function togglePortStrategy(address _portStrategy, address _token) external override requiresCoreRouter {
403 function updatePortStrategy(address _portStrategy, address _token, uint256 _dailyManagementLimit)
404 external
405 override
406 requiresCoreRouter
407: {
414 function setCoreBranchRouter(address _coreBranchRouter, address _coreBranchBridgeAgent)
415 external
416 override
417 requiresCoreRouter
418: {
GitHub: 135, 144, 167, 188, 226, 237, 246, 277, 288, 319, 331, 338, 348, 355, 362, 375, 382, 396, 403, 414
File: src/CoreBranchRouter.sol
86: function executeNoSettlement(bytes calldata _params) external payable virtual override requiresAgentExecutor {
GitHub: 86
File: src/CoreRootRouter.sol
297 function executeResponse(bytes calldata _encodedData, uint16 _srcChainId)
298 external
299 payable
300 override
301 requiresExecutor
302: {
332: function execute(bytes calldata _encodedData, uint16) external payable override requiresExecutor {
350 function executeDepositSingle(bytes memory, DepositParams memory, uint16)
351 external
352 payable
353 override
354 requiresExecutor
355: {
360 function executeDepositMultiple(bytes calldata, DepositMultipleParams memory, uint16)
361 external
362 payable
363 override
364 requiresExecutor
365: {
370: function executeSigned(bytes memory, address, uint16) external payable override requiresExecutor {
375 function executeSignedDepositSingle(bytes memory, DepositParams memory, address, uint16)
376 external
377 payable
378 override
379 requiresExecutor
380: {
385 function executeSignedDepositMultiple(bytes memory, DepositMultipleParams memory, address, uint16)
386 external
387 payable
388 override
389 requiresExecutor
390: {
GitHub: 297, 332, 350, 360, 370, 375, 385
File: src/MulticallRootRouter.sol
123: function executeResponse(bytes memory, uint16) external payable override {
137: function execute(bytes calldata encodedData, uint16) external payable override lock requiresExecutor {
203: function executeDepositSingle(bytes calldata, DepositParams calldata, uint16) external payable override {
223 function executeSigned(bytes calldata encodedData, address userAccount, uint16)
224 external
225 payable
226 override
227 lock
228 requiresExecutor
229: {
312 function executeSignedDepositSingle(bytes calldata encodedData, DepositParams calldata, address userAccount, uint16)
313 external
314 payable
315 override
316 requiresExecutor
317 lock
318: {
401 function executeSignedDepositMultiple(
402 bytes calldata encodedData,
403 DepositMultipleParams calldata,
404 address userAccount,
405 uint16
406: ) external payable override requiresExecutor lock {
GitHub: 123, 137, 203, 223, 312, 401
File: src/MulticallRootRouterLibZip.sol
37: function _decode(bytes calldata data) internal pure override returns (bytes memory) {
GitHub: 37
File: src/RootBridgeAgent.sol
135: function getSettlementEntry(uint32 _settlementNonce) external view override returns (Settlement memory) {
160 function callOut(
161 address payable _refundee,
162 address _recipient,
163 uint16 _dstChainId,
164 bytes calldata _params,
165 GasParams calldata _gParams
166: ) external payable override lock requiresRouter {
175 function callOutAndBridge(
176 address payable _refundee,
177 address _recipient,
178 uint16 _dstChainId,
179 bytes calldata _params,
180 SettlementInput calldata _sParams,
181 GasParams calldata _gParams,
182 bool _hasFallbackToggled
183: ) external payable override lock requiresRouter {
202 function callOutAndBridgeMultiple(
203 address payable _refundee,
204 address _recipient,
205 uint16 _dstChainId,
206 bytes calldata _params,
207 SettlementMultipleInput calldata _sParams,
208 GasParams calldata _gParams,
209 bool _hasFallbackToggled
210: ) external payable override lock requiresRouter {
233 function retrySettlement(
234 uint32 _settlementNonce,
235 address _recipient,
236 bytes calldata _params,
237 GasParams calldata _gParams,
238 bool _hasFallbackToggled
239: ) external payable override lock {
299: function redeemSettlement(uint32 _settlementNonce) external override lock {
351 function bridgeIn(address _recipient, DepositParams memory _dParams, uint256 _srcChainId)
352 public
353 override
354 requiresAgentExecutor
355: {
387 function bridgeInMultiple(address _recipient, DepositMultipleParams calldata _dParams, uint256 _srcChainId)
388 external
389 override
390 requiresAgentExecutor
391: {
434 function lzReceiveNonBlocking(
435 address _endpoint,
436 uint16 _srcChainId,
437 bytes calldata _srcAddress,
438 bytes calldata _payload
439: ) public override requiresEndpoint(_endpoint, _srcChainId, _srcAddress) {
1170: function approveBranchBridgeAgent(uint256 _branchChainId) external override requiresManager {
1176 function syncBranchBridgeAgent(address _newBranchBridgeAgent, uint256 _branchChainId)
1177 external
1178 override
1179 requiresPort
1180: {
GitHub: 135, 160, 175, 202, 233, 299, 351, 387, 434, 1170, 1176
File: src/RootPort.sol
166: function renounceOwnership() public payable override onlyOwner {
175 function getLocalToken(address _localAddress, uint256 _srcChainId, uint256 _dstChainId)
176 external
177 view
178 override
179 returns (address)
180: {
200 function getUnderlyingTokenFromGlobal(address _globalAddress, uint256 _srcChainId)
201 external
202 view
203 override
204 returns (address)
205: {
211: function isGlobalToken(address _globalAddress, uint256 _srcChainId) external view override returns (bool) {
216: function isLocalToken(address _localAddress, uint256 _srcChainId) external view override returns (bool) {
230: function isUnderlyingToken(address _underlyingToken, uint256 _srcChainId) external view override returns (bool) {
239 function setAddresses(
240 address _globalAddress,
241 address _localAddress,
242 address _underlyingAddress,
243 uint256 _srcChainId
244: ) external override requiresCoreRootRouter {
259 function setLocalAddress(address _globalAddress, address _localAddress, uint256 _srcChainId)
260 external
261 override
262 requiresCoreRootRouter
263: {
277 function bridgeToRoot(address _recipient, address _hToken, uint256 _amount, uint256 _deposit, uint256 _srcChainId)
278 external
279 override
280 requiresBridgeAgent
281: {
294 function bridgeToRootFromLocalBranch(address _from, address _hToken, uint256 _amount)
295 external
296 override
297 requiresLocalBranchPort
298: {
304 function bridgeToLocalBranchFromRoot(address _to, address _hToken, uint256 _amount)
305 external
306 override
307 requiresLocalBranchPort
308: {
315 function burn(address _from, address _hToken, uint256 _amount, uint256 _srcChainId)
316 external
317 override
318 requiresBridgeAgent
319: {
325 function burnFromLocalBranch(address _from, address _hToken, uint256 _amount)
326 external
327 override
328 requiresLocalBranchPort
329: {
336 function mintToLocalBranch(address _to, address _hToken, uint256 _amount)
337 external
338 override
339 requiresLocalBranchPort
340: {
350: function fetchVirtualAccount(address _user) external override returns (VirtualAccount account) {
369 function toggleVirtualAccountApproved(VirtualAccount _userAccount, address _router)
370 external
371 override
372 requiresBridgeAgent
373: {
382: function addBridgeAgent(address _manager, address _bridgeAgent) external override requiresBridgeAgentFactory {
393 function syncBranchBridgeAgentWithRoot(
394 address _newBranchBridgeAgent,
395 address _rootBridgeAgent,
396 uint256 _branchChainId
397: ) external override requiresCoreRootRouter {
414: function toggleBridgeAgent(address _bridgeAgent) external override onlyOwner {
421: function addBridgeAgentFactory(address _bridgeAgentFactory) external override onlyOwner {
431: function toggleBridgeAgentFactory(address _bridgeAgentFactory) external override onlyOwner {
438 function addNewChain(
439 address _coreBranchBridgeAgentAddress,
440 uint256 _chainId,
441 string memory _wrappedGasTokenName,
442 string memory _wrappedGasTokenSymbol,
443 uint8 _wrappedGasTokenDecimals,
444 address _newLocalBranchWrappedNativeTokenAddress,
445 address _newUnderlyingBranchWrappedNativeTokenAddress
446: ) external override onlyOwner {
483: function addEcosystemToken(address _ecoTokenGlobalAddress) external override onlyOwner {
509: function setCoreRootRouter(address _coreRootRouter, address _coreRootBridgeAgent) external override onlyOwner {
521 function setCoreBranchRouter(
522 address _refundee,
523 address _coreBranchRouter,
524 address _coreBranchBridgeAgent,
525 uint16 _dstChainId,
526 GasParams calldata _gParams
527: ) external payable override onlyOwner {
539 function syncNewCoreBranchRouter(address _coreBranchRouter, address _coreBranchBridgeAgent, uint16 _dstChainId)
540 external
541 override
542 onlyOwner
543: {
GitHub: 166, 175, 200, 211, 216, 230, 239, 259, 277, 294, 304, 315, 325, 336, 350, 369, 382, 393, 414, 421, 431, 438, 483, 509, 521, 539
File: src/VirtualAccount.sol
51: function withdrawNative(uint256 _amount) external override requiresApprovedCaller {
56: function withdrawERC20(address _token, uint256 _amount) external override requiresApprovedCaller {
61: function withdrawERC721(address _token, uint256 _tokenId) external override requiresApprovedCaller {
66: function call(Call[] calldata calls) external override requiresApprovedCaller returns (bytes[] memory returnData) {
119: function onERC721Received(address, address, uint256, bytes calldata) external pure override returns (bytes4) {
124 function onERC1155Received(address, address, uint256, uint256, bytes calldata)
125 external
126 pure
127 override
128 returns (bytes4)
129: {
134 function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata)
135 external
136 pure
137 override
138 returns (bytes4)
139: {
GitHub: 51, 56, 61, 66, 119, 124, 134
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
56: function initialize(address _coreRootBridgeAgent) external override onlyOwner {
79 function createBridgeAgent(
80 address _newBranchRouterAddress,
81 address _rootBridgeAgentAddress,
82 address _rootBridgeAgentFactoryAddress
83: ) external virtual override returns (address newBridgeAgent) {
File: src/token/ERC20hTokenBranch.sol
29: function mint(address account, uint256 amount) external override onlyOwner returns (bool) {
35: function burn(uint256 amount) public override onlyOwner {
Passing zero as a function argument can sometimes result in a security issue (e.g. passing zero as the slippage parameter). Consider using a constant
variable with a descriptive name, so it's clear that the argument is intentionally being used, and for the right reasons.
There are 4 instances of this issue:
File: src/ArbitrumBranchBridgeAgent.sol
105: IRootBridgeAgent(_rootBridgeAgentAddress).lzReceive(rootChainId, "", 0, _calldata);
114 IRootBridgeAgent(rootBridgeAgentAddress).lzReceive(
115 rootChainId, "", 0, abi.encodePacked(bytes1(0x09), _settlementNonce)
116: );
File: src/RootBridgeAgent.sol
837: IBranchBridgeAgent(callee).lzReceive(0, "", 0, _payload);
929: IBranchBridgeAgent(callee).lzReceive(0, "", 0, payload);
The default value for variables is zero, so initializing them to zero is superfluous.
There are 17 instances of this issue:
see instances
File: src/BaseBranchRouter.sol
192: for (uint256 i = 0; i < _hTokens.length;) {
GitHub: 192
File: src/BranchBridgeAgent.sol
447: for (uint256 i = 0; i < deposit.tokens.length;) {
513: for (uint256 i = 0; i < numOfAssets;) {
File: src/BranchPort.sol
257: for (uint256 i = 0; i < length;) {
305: for (uint256 i = 0; i < length;) {
File: src/MulticallRootRouter.sol
278: for (uint256 i = 0; i < outputParams.outputTokens.length;) {
367: for (uint256 i = 0; i < outputParams.outputTokens.length;) {
455: for (uint256 i = 0; i < outputParams.outputTokens.length;) {
557: for (uint256 i = 0; i < outputTokens.length;) {
File: src/RootBridgeAgent.sol
318: for (uint256 i = 0; i < settlement.hTokens.length;) {
399: for (uint256 i = 0; i < length;) {
1070: for (uint256 i = 0; i < hTokens.length;) {
File: src/RootBridgeAgentExecutor.sol
281: for (uint256 i = 0; i < uint256(uint8(numOfAssets));) {
GitHub: 281
File: src/VirtualAccount.sol
70: for (uint256 i = 0; i < length;) {
90: for (uint256 i = 0; i < length;) {
File: src/interfaces/BridgeAgentConstants.sol
13: uint8 internal constant STATUS_READY = 0;
23: uint8 internal constant STATUS_SUCCESS = 0;
There are 13 instances of this issue:
File: src/BaseBranchRouter.sol
213: require(_unlocked == 1);
GitHub: 213
File: src/BranchBridgeAgent.sol
923: require(_unlocked == 1);
GitHub: 923
File: src/BranchPort.sol
567: require(_unlocked == 1);
GitHub: 567
File: src/CoreRootRouter.sol
356: revert();
366: revert();
371: revert();
381: revert();
391: revert();
GitHub: 356, 366, 371, 381, 391
File: src/MulticallRootRouter.sol
124: revert();
204: revert();
210: revert();
591: require(_unlocked == 1);
File: src/RootBridgeAgent.sol
1191: require(_unlocked == 1);
GitHub: 1191
This helps to make tracking changes across commits easier, among other reasons. The instances below are the second+ contract/library within each file
There are 4 instances of this issue:
File: src/ArbitrumBranchBridgeAgent.sol
31 contract ArbitrumBranchBridgeAgent is BranchBridgeAgent {
32 /*///////////////////////////////////////////////////////////////
33 CONSTRUCTOR
34 //////////////////////////////////////////////////////////////*/
35
36 /**
37 * @notice Constructor for Arbitrum Branch Bridge Agent.
38 * @param _localChainId Local Chain Layer Zero Id.
39 * @param _rootBridgeAgentAddress Root Bridge Agent Address.
40 * @param _localRouterAddress Local Core Branch Router Address.
41 * @param _localPortAddress Local Branch Port Address.
42: */
GitHub: 31
File: src/BranchBridgeAgent.sol
45: contract BranchBridgeAgent is IBranchBridgeAgent, BridgeAgentConstants {
GitHub: 45
File: src/BranchBridgeAgentExecutor.sol
29: contract BranchBridgeAgentExecutor is Ownable, BridgeAgentConstants {
GitHub: 29
File: src/RootBridgeAgentExecutor.sol
27 contract RootBridgeAgentExecutor is Ownable, BridgeAgentConstants {
28 /*///////////////////////////////////////////////////////////////
29 CONSTRUCTOR
30 //////////////////////////////////////////////////////////////*/
31 /**
32 * @notice Constructor for Root Bridge Agent Executor.
33 * @param _rootBridgeAgent the owner of the contract in charge of calling the different execution functions.
34: */
GitHub: 27
Consider using just one method in a single file
There are 10 instances of this issue:
see instances
File: src/ArbitrumBranchPort.sol
14: contract ArbitrumBranchPort is BranchPort, IArbitrumBranchPort {
GitHub: 14
File: src/BaseBranchRouter.sol
25: contract BaseBranchRouter is IBranchRouter, Ownable {
GitHub: 25
File: src/BranchBridgeAgent.sol
45: contract BranchBridgeAgent is IBranchBridgeAgent, BridgeAgentConstants {
GitHub: 45
File: src/BranchPort.sol
17: contract BranchPort is Ownable, IBranchPort {
GitHub: 17
File: src/CoreRootRouter.sol
38 contract CoreRootRouter is IRootRouter, Ownable {
39 /*///////////////////////////////////////////////////////////////
40 CORE ROOT ROUTER STATE
41 //////////////////////////////////////////////////////////////*/
42
43: /// @notice Boolean to indicate if the contract is in set up mode.
GitHub: 38
File: src/MulticallRootRouter.sol
57: contract MulticallRootRouter is IRootRouter, Ownable {
GitHub: 57
File: src/RootBridgeAgent.sol
32: contract RootBridgeAgent is IRootBridgeAgent, BridgeAgentConstants {
GitHub: 32
File: src/RootPort.sol
16: contract RootPort is Ownable, IRootPort {
GitHub: 16
File: src/factories/ERC20hTokenBranchFactory.sol
12 contract ERC20hTokenBranchFactory is Ownable, IERC20hTokenBranchFactory {
13: /// @notice Local Network Identifier.
GitHub: 12
File: src/factories/ERC20hTokenRootFactory.sol
12 contract ERC20hTokenRootFactory is Ownable, IERC20hTokenRootFactory {
13: /// @notice Local Network Identifier.
GitHub: 12
There are two primary standards for NFTs - ERC-721 and ERC-1155. Supporting one but not the other excludes half of the available market.
There are 2 instances of this issue:
File: src/VirtualAccount.sol
17 contract VirtualAccount is IVirtualAccount, ERC1155Receiver {
18 using SafeTransferLib for address;
19
20 /// @inheritdoc IVirtualAccount
21 address public immutable override userAddress;
22
23 /// @inheritdoc IVirtualAccount
24 address public immutable override localPortAddress;
25
26 /*//////////////////////////////////////////////////////////////
27 CONSTRUCTOR
28 //////////////////////////////////////////////////////////////*/
29
30 /**
31 * @notice Constructor for Virtual Account.
32 * @param _userAddress Address of the user account.
33 * @param _localPortAddress Address of the root port contract.
34 */
35 constructor(address _userAddress, address _localPortAddress) {
36 userAddress = _userAddress;
37 localPortAddress = _localPortAddress;
38 }
39
40 /*//////////////////////////////////////////////////////////////
41 FALLBACK FUNCTIONS
42 //////////////////////////////////////////////////////////////*/
43
44 receive() external payable {}
45
46 /*//////////////////////////////////////////////////////////////
47 EXTERNAL FUNCTIONS
48 //////////////////////////////////////////////////////////////*/
49
50 /// @inheritdoc IVirtualAccount
51 function withdrawNative(uint256 _amount) external override requiresApprovedCaller {
52 msg.sender.safeTransferETH(_amount);
53 }
54
55 /// @inheritdoc IVirtualAccount
56 function withdrawERC20(address _token, uint256 _amount) external override requiresApprovedCaller {
57 _token.safeTransfer(msg.sender, _amount);
58 }
59
60 /// @inheritdoc IVirtualAccount
61 function withdrawERC721(address _token, uint256 _tokenId) external override requiresApprovedCaller {
62 ERC721(_token).transferFrom(address(this), msg.sender, _tokenId);
63 }
64
65 /// @inheritdoc IVirtualAccount
66 function call(Call[] calldata calls) external override requiresApprovedCaller returns (bytes[] memory returnData) {
67 uint256 length = calls.length;
68 returnData = new bytes[](length);
69
70 for (uint256 i = 0; i < length;) {
71 bool success;
72 Call calldata _call = calls[i];
73
74 if (isContract(_call.target)) (success, returnData[i]) = _call.target.call(_call.callData);
75
76 if (!success) revert CallFailed();
77
78 unchecked {
79 ++i;
80 }
81 }
82 }
83
84 /// @inheritdoc IVirtualAccount
85 function payableCall(PayableCall[] calldata calls) public payable returns (bytes[] memory returnData) {
86 uint256 valAccumulator;
87 uint256 length = calls.length;
88 returnData = new bytes[](length);
89 PayableCall calldata _call;
90 for (uint256 i = 0; i < length;) {
91 _call = calls[i];
92 uint256 val = _call.value;
93 // Humanity will be a Type V Kardashev Civilization before this overflows - andreas
94 // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256
95 unchecked {
96 valAccumulator += val;
97 }
98
99 bool success;
100
101 if (isContract(_call.target)) (success, returnData[i]) = _call.target.call{value: val}(_call.callData);
102
103 if (!success) revert CallFailed();
104
105 unchecked {
106 ++i;
107 }
108 }
109
110 // Finally, make sure the msg.value = SUM(call[0...i].value)
111 if (msg.value != valAccumulator) revert CallFailed();
112 }
113
114 /*//////////////////////////////////////////////////////////////
115 EXTERNAL HOOKS
116 //////////////////////////////////////////////////////////////*/
117
118 /// @inheritdoc IERC721Receiver
119 function onERC721Received(address, address, uint256, bytes calldata) external pure override returns (bytes4) {
120 return this.onERC721Received.selector;
121 }
122
123 /// @inheritdoc IERC1155Receiver
124 function onERC1155Received(address, address, uint256, uint256, bytes calldata)
125 external
126 pure
127 override
128 returns (bytes4)
129 {
130 return this.onERC1155Received.selector;
131 }
132
133 /// @inheritdoc IERC1155Receiver
134 function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata)
135 external
136 pure
137 override
138 returns (bytes4)
139 {
140 return this.onERC1155BatchReceived.selector;
141 }
142
143 /*//////////////////////////////////////////////////////////////
144 INTERNAL HELPERS
145 //////////////////////////////////////////////////////////////*/
146
147 function isContract(address addr) internal view returns (bool) {
148 uint256 size;
149 assembly {
150 size := extcodesize(addr)
151 }
152 return size > 0;
153 }
154
155 /*///////////////////////////////////////////////////////////////
156 MODIFIERS
157 //////////////////////////////////////////////////////////////*/
158
159 /// @notice Modifier that verifies msg sender is the approved to use the virtual account. Either the owner or an approved router.
160 modifier requiresApprovedCaller() {
161 if (!IRootPort(localPortAddress).isRouterApproved(this, msg.sender)) {
162 if (msg.sender != userAddress) {
163 revert UnauthorizedCaller();
164 }
165 }
166 _;
167 }
168: }
GitHub: 17
File: src/interfaces/IVirtualAccount.sol
27 interface IVirtualAccount is IERC721Receiver {
28 /**
29 * @notice Returns the address of the user that owns the VirtualAccount.
30 * @return The address of the user that owns the VirtualAccount.
31 */
32 function userAddress() external view returns (address);
33
34 /**
35 * @notice Returns the address of the local port.
36 * @return The address of the local port.
37 */
38 function localPortAddress() external view returns (address);
39
40 /**
41 * @notice Withdraws native tokens from the VirtualAccount.
42 * @param _amount The amount of tokens to withdraw.
43 */
44 function withdrawNative(uint256 _amount) external;
45
46 /**
47 * @notice Withdraws ERC20 tokens from the VirtualAccount.
48 * @param _token The address of the ERC20 token to withdraw.
49 * @param _amount The amount of tokens to withdraw.
50 */
51 function withdrawERC20(address _token, uint256 _amount) external;
52
53 /**
54 * @notice Withdraws ERC721 tokens from the VirtualAccount.
55 * @param _token The address of the ERC721 token to withdraw.
56 * @param _tokenId The id of the token to withdraw.
57 */
58 function withdrawERC721(address _token, uint256 _tokenId) external;
59
60 /**
61 * @notice Aggregate calls ensuring each call is successful. Inspired by `Multicall2` contract.
62 * @param callInput The call to make.
63 * @return The return data of the call.
64 */
65 function call(Call[] calldata callInput) external returns (bytes[] memory);
66
67 /**
68 * @notice Aggregate calls with a msg value ensuring each call is successful. Inspired by `Multicall3` contract.
69 * @param calls The calls to make.
70 * @return The return data of the calls.
71 * @dev Reverts if msg.value is less than the sum of the call values.
72 */
73 function payableCall(PayableCall[] calldata calls) external payable returns (bytes[] memory);
74
75 /*///////////////////////////////////////////////////////////////
76 ERRORS
77 //////////////////////////////////////////////////////////////*/
78
79 error CallFailed();
80
81 error UnauthorizedCaller();
82: }
GitHub: 27
According to the Solidity Style Guide, non-external
/public
function names should begin with an underscore
There are 2 instances of this issue:
File: src/RootPort.sol
359: function addVirtualAccount(address _user) internal returns (VirtualAccount newAccount) {
GitHub: 359
File: src/VirtualAccount.sol
147: function isContract(address addr) internal view returns (bool) {
GitHub: 147
Even assembly can benefit from using readable constants instead of hex/numeric literals
There are 125 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
115: rootChainId, "", 0, abi.encodePacked(bytes1(0x09), _settlementNonce)
GitHub: 115
File: src/ArbitrumCoreBranchRouter.sol
62: bytes memory payload = abi.encodePacked(bytes1(0x02), params);
115: bytes memory payload = abi.encodePacked(bytes1(0x04), data);
127: if (_data[0] == 0x02) {
146: } else if (_data[0] == 0x03) {
152: } else if (_data[0] == 0x04) {
157: } else if (_data[0] == 0x05) {
162: } else if (_data[0] == 0x06) {
GitHub: 62, 115, 127, 146, 152, 157, 162
File: src/BranchBridgeAgent.sol
188: bytes memory payload = abi.encodePacked(bytes1(0x00), depositNonce++, _params);
202: bytes memory payload = abi.encodePacked(bytes1(0x01), depositNonce++, _params);
220: bytes1(0x02), _depositNonce, _dParams.hToken, _dParams.token, _dParams.amount, _dParams.deposit, _params
242: bytes1(0x03),
269: bytes memory payload = abi.encodePacked(bytes1(0x04), msg.sender, depositNonce++, _params);
288: _hasFallbackToggled ? bytes1(0x85) : bytes1(0x05),
318: _hasFallbackToggled ? bytes1(0x86) : bytes1(0x06),
399: bytes1(0x03),
387: _hasFallbackToggled ? bytes1(0x86) : bytes1(0x06),
374: bytes1(0x02),
363: _hasFallbackToggled ? bytes1(0x85) : bytes1(0x05),
427: bytes memory payload = abi.encodePacked(bytes1(0x08), msg.sender, _depositNonce);
474: bytes memory payload = abi.encodePacked(_hasFallbackToggled ? bytes1(0x87) : bytes1(0x07), params);
581: 150,
593: bytes1 flag = _payload[0] & 0x7F;
599: if (flag == 0x00) {
616: } else if (flag == 0x01) {
638: } else if (flag == 0x02) {
663: } else if (flag == 0x03) {
681: } else if (flag == 0x04) {
643: nonce = uint32(bytes4(_payload[22:26]));
651: _payload[0] == 0x82,
629: _payload[0] == 0x81,
790: abi.encodePacked(bytes1(0x09), _settlementNonce),
942: if (_srcAddress.length != 40) revert LayerZeroUnauthorizedCaller();
943: if (rootBridgeAgentAddress != address(uint160(bytes20(_srcAddress[20:])))) revert LayerZeroUnauthorizedCaller();
GitHub: 188, 202, 220, 242, 269, 288, 288, 318, 318, 399, 387, 387, 374, 363, 363, 427, 474, 474, 581, 593, 599, 616, 638, 663, 681, 643, 643, 651, 629, 790, 942, 943
File: src/BranchBridgeAgentExecutor.sol
75: hToken: address(uint160(bytes20(_payload[PARAMS_TKN_START_SIGNED:45]))),
76: token: address(uint160(bytes20(_payload[45:65]))),
77: amount: uint256(bytes32(_payload[65:97])),
78: deposit: uint256(bytes32(_payload[97:PARAMS_SETTLEMENT_OFFSET]))
GitHub: 75, 76, 76, 77, 77, 78
File: src/BranchPort.sol
299: if (length > 255) revert InvalidInputArrays();
GitHub: 299
File: src/CoreBranchRouter.sol
51: bytes memory payload = abi.encodePacked(bytes1(0x01), params);
43: function addGlobalToken(address _globalAddress, uint256 _dstChainId, GasParams[3] calldata _gParams)
75: bytes memory payload = abi.encodePacked(bytes1(0x02), params);
88: if (_params[0] == 0x01) {
100: } else if (_params[0] == 0x02) {
115: } else if (_params[0] == 0x03) {
121: } else if (_params[0] == 0x04) {
127: } else if (_params[0] == 0x05) {
133: } else if (_params[0] == 0x06) {
140: } else if (_params[0] == 0x07) {
181: bytes memory payload = abi.encodePacked(bytes1(0x03), params);
229: bytes memory payload = abi.encodePacked(bytes1(0x04), params);
GitHub: 51, 43, 75, 88, 100, 115, 121, 127, 133, 140, 181, 229
File: src/CoreRootRouter.sol
136: bytes memory payload = abi.encodePacked(bytes1(0x02), params);
171: bytes memory payload = abi.encodePacked(bytes1(0x03), params);
196: bytes memory payload = abi.encodePacked(bytes1(0x04), params);
223: bytes memory payload = abi.encodePacked(bytes1(0x05), params);
254: bytes memory payload = abi.encodePacked(bytes1(0x06), params);
284: bytes memory payload = abi.encodePacked(bytes1(0x07), params);
307: if (funcId == 0x02) {
314: } else if (funcId == 0x03) {
320: } else if (funcId == 0x04) {
337: if (funcId == 0x01) {
434: bytes memory payload = abi.encodePacked(bytes1(0x01), params);
GitHub: 136, 171, 196, 223, 254, 284, 307, 314, 320, 337, 434
File: src/MulticallRootRouter.sol
142: if (funcId == 0x01) {
150: } else if (funcId == 0x02) {
174: } else if (funcId == 0x03) {
234: if (funcId == 0x01) {
242: } else if (funcId == 0x02) {
265: } else if (funcId == 0x03) {
323: if (funcId == 0x01) {
331: } else if (funcId == 0x02) {
354: } else if (funcId == 0x03) {
411: if (funcId == 0x01) {
419: } else if (funcId == 0x02) {
442: } else if (funcId == 0x03) {
GitHub: 142, 150, 174, 234, 242, 265, 323, 331, 354, 411, 419, 442
File: src/RootBridgeAgent.sol
168: bytes memory payload = abi.encodePacked(bytes1(0x00), _recipient, settlementNonce++, _params);
292: bytes memory payload = abi.encodePacked(bytes1(0x03), settlementOwner, _settlementNonce);
426: 150,
444: if (_payload[0] == 0x00) {
467: } else if (_payload[0] == 0x01) {
490: } else if (_payload[0] == 0x02) {
513: } else if (_payload[0] == 0x03) {
539: } else if (_payload[0] == 0x04) {
577: } else if (_payload[0] & 0x7F == 0x05) {
617: } else if (_payload[0] & 0x7F == 0x06) {
657: } else if (_payload[0] & 0x7F == 0x07) {
699: } else if (_payload[0] == 0x08) {
718: } else if (_payload[0] == 0x09) {
684: _payload[0] == 0x87,
640: _payload[0] == 0x86,
600: _payload[0] == 0x85,
515: nonce = uint32(bytes4(_payload[2:6]));
894: _hasFallbackToggled ? bytes1(0x82) : bytes1(0x02),
880: _hasFallbackToggled ? bytes1(0x81) : bytes1(0x01),
943: abi.encodePacked(bytes1(0x04), _depositNonce),
993: _hasFallbackToggled ? bytes1(0x81) : bytes1(0x01),
1090: _hasFallbackToggled ? bytes1(0x02) & 0x0F : bytes1(0x02),
1210: if (_srcAddress.length != 40) revert LayerZeroUnauthorizedCaller();
GitHub: 168, 292, 426, 444, 467, 490, 513, 539, 577, 577, 617, 617, 657, 657, 699, 718, 684, 640, 600, 515, 894, 894, 880, 880, 943, 993, 993, 1090, 1090, 1090, 1210
File: src/RootBridgeAgentExecutor.sol
91: token: address(uint160(bytes20(_payload[PARAMS_TKN_START_SIGNED:45]))),
92: amount: uint256(bytes32(_payload[45:77])),
93: deposit: uint256(bytes32(_payload[77:PARAMS_TKN_SET_SIZE]))
175: hToken: address(uint160(bytes20(_payload[PARAMS_TKN_START_SIGNED:45]))),
176: token: address(uint160(bytes20(_payload[45:65]))),
177: amount: uint256(bytes32(_payload[65:97])),
178: deposit: uint256(bytes32(_payload[97:PARAMS_SETTLEMENT_OFFSET]))
274: uint32 nonce = uint32(bytes4(_dParams[PARAMS_START:5]));
GitHub: 91, 92, 92, 93, 175, 176, 176, 177, 177, 178, 274
File: src/interfaces/ICoreBranchRouter.sol
38: function addGlobalToken(address _globalAddress, uint256 _dstChainId, GasParams[3] calldata _gasParams)
GitHub: 38
When an action is triggered based on a user's action, not being able to filter based on who triggered the action makes event processing a lot more cumbersome. Including the msg.sender
the events of these types of action will make events much more useful to end users, especially when msg.sender
is not tx.origin
.
There are 27 instances of this issue:
File: src/BranchBridgeAgent.sol
689: emit LogFallback(nonce);
700: emit LogExecute(nonce);
File: src/BranchPort.sol
218: emit DebtRepaid(_strategy, _token, amountToWithdraw);
344: emit BridgeAgentFactoryAdded(_newBridgeAgentFactory);
351: emit BridgeAgentFactoryToggled(_newBridgeAgentFactory);
358: emit BridgeAgentToggled(_bridgeAgent);
371: emit StrategyTokenAdded(_token, _minimumReservesRatio);
378: emit StrategyTokenToggled(_token);
392: emit PortStrategyAdded(_portStrategy, _token, _dailyManagementLimit);
399: emit PortStrategyToggled(_portStrategy, _token);
410: emit PortStrategyUpdated(_portStrategy, _token, _dailyManagementLimit);
423: emit CoreBranchSet(_coreBranchRouter, _coreBranchBridgeAgent);
GitHub: 218, 344, 351, 358, 371, 378, 392, 399, 410, 423
File: src/RootBridgeAgent.sol
726: emit LogFallback(nonce, _srcChainId);
736: emit LogExecute(nonce, _srcChainId);
File: src/RootPort.sol
255: emit LocalTokenAdded(_underlyingAddress, _localAddress, _globalAddress, _srcChainId);
269: emit GlobalTokenAdded(_localAddress, _globalAddress, _srcChainId);
365: emit VirtualAccountCreated(_user, address(newAccount));
389: emit BridgeAgentAdded(_bridgeAgent, _manager);
406: emit BridgeAgentSynced(_newBranchBridgeAgent, _rootBridgeAgent, _branchChainId);
417: emit BridgeAgentToggled(_bridgeAgent);
427: emit BridgeAgentFactoryAdded(_bridgeAgentFactory);
434: emit BridgeAgentFactoryToggled(_bridgeAgentFactory);
479: emit NewChainAdded(_chainId);
505: emit EcosystemTokenAdded(_ecoTokenGlobalAddress);
517: emit CoreRootSet(_coreRootRouter, _coreRootBridgeAgent);
535: emit CoreBranchSet(_coreBranchRouter, _coreBranchBridgeAgent, _dstChainId);
549: emit CoreBranchSynced(_coreBranchRouter, _coreBranchBridgeAgent, _dstChainId);
GitHub: 255, 269, 365, 389, 406, 417, 427, 434, 479, 505, 517, 535, 549
Doing so will significantly increase centralization, but will help to prevent hackers from using stolen tokens
There are 12 instances of this issue:
see instances
File: src/ArbitrumCoreBranchRouter.sol
37 contract ArbitrumCoreBranchRouter is CoreBranchRouter {
38 /*///////////////////////////////////////////////////////////////
39 CONSTRUCTOR
40 //////////////////////////////////////////////////////////////*/
41 /**
42 * @notice Constructor for Arbitrum Core Branch Router.
43: */
GitHub: 37
File: src/BaseBranchRouter.sol
25: contract BaseBranchRouter is IBranchRouter, Ownable {
GitHub: 25
File: src/BranchPort.sol
17: contract BranchPort is Ownable, IBranchPort {
GitHub: 17
File: src/CoreBranchRouter.sol
18 contract CoreBranchRouter is ICoreBranchRouter, BaseBranchRouter {
19: /// @notice hToken Factory Address.
GitHub: 18
File: src/CoreRootRouter.sol
38 contract CoreRootRouter is IRootRouter, Ownable {
39 /*///////////////////////////////////////////////////////////////
40 CORE ROOT ROUTER STATE
41 //////////////////////////////////////////////////////////////*/
42
43: /// @notice Boolean to indicate if the contract is in set up mode.
GitHub: 38
File: src/RootBridgeAgent.sol
32: contract RootBridgeAgent is IRootBridgeAgent, BridgeAgentConstants {
GitHub: 32
File: src/RootPort.sol
16: contract RootPort is Ownable, IRootPort {
GitHub: 16
File: src/VirtualAccount.sol
17: contract VirtualAccount is IVirtualAccount, ERC1155Receiver {
GitHub: 17
File: src/factories/ERC20hTokenBranchFactory.sol
12 contract ERC20hTokenBranchFactory is Ownable, IERC20hTokenBranchFactory {
13: /// @notice Local Network Identifier.
GitHub: 12
File: src/factories/ERC20hTokenRootFactory.sol
12 contract ERC20hTokenRootFactory is Ownable, IERC20hTokenRootFactory {
13: /// @notice Local Network Identifier.
GitHub: 12
File: src/token/ERC20hTokenBranch.sol
12: contract ERC20hTokenBranch is ERC20, Ownable, IERC20hTokenBranch {
GitHub: 12
File: src/token/ERC20hTokenRoot.sol
12 contract ERC20hTokenRoot is ERC20, Ownable, IERC20hTokenRoot {
13: /// @inheritdoc IERC20hTokenRoot
GitHub: 12
[N‑43] Consider using SafeTransferLib.safeTransferETH()
or Address.sendValue()
for clearer semantic meaning
These Functions indicate their purpose with their name more clearly than using low-level calls.
There are 3 instances of this issue:
File: src/ArbitrumBranchBridgeAgent.sol
103: _rootBridgeAgentAddress.call{value: msg.value}("");
GitHub: 103
File: src/RootBridgeAgent.sol
835: callee.call{value: msg.value}("");
927: callee.call{value: _value}("");
The identifier is imported but never used within the file
There are 15 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
/// @audit IBranchBridgeAgent
6: import {GasParams, IBranchBridgeAgent} from "./interfaces/IBranchBridgeAgent.sol";
GitHub: 6
File: src/BaseBranchRouter.sol
/// @audit DepositParams
16: DepositParams,
/// @audit DepositMultipleParams
18: DepositMultipleParams,
File: src/BranchBridgeAgent.sol
/// @audit ILayerZeroReceiver
15: ILayerZeroReceiver,
GitHub: 15
File: src/CoreBranchRouter.sol
/// @audit IBranchRouter
9: import {IBranchRouter} from "./interfaces/IBranchRouter.sol";
GitHub: 9
File: src/RootBridgeAgent.sol
/// @audit ILayerZeroReceiver
18: ILayerZeroReceiver,
GitHub: 18
File: src/RootBridgeAgentExecutor.sol
/// @audit IRootBridgeAgent
7: import {IRootBridgeAgent} from "./interfaces/IRootBridgeAgent.sol";
GitHub: 7
File: src/VirtualAccount.sol
/// @audit IERC1155Receiver
10: import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
/// @audit IERC721Receiver
11: import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
/// @audit ArbitrumBranchBridgeAgent
6: import {ArbitrumBranchBridgeAgent, DeployArbitrumBranchBridgeAgent} from "../ArbitrumBranchBridgeAgent.sol";
GitHub: 6
File: src/factories/ERC20hTokenRootFactory.sol
/// @audit ERC20
6: import {ERC20} from "solmate/tokens/ERC20.sol";
GitHub: 6
File: src/interfaces/IBranchBridgeAgent.sol
/// @audit DepositParams
11: DepositParams,
/// @audit DepositMultipleParams
12: DepositMultipleParams,
/// @audit SettlementParams
13: SettlementParams,
File: src/interfaces/IRootBridgeAgent.sol
/// @audit SettlementParams
13: SettlementParams
GitHub: 13
Array entries are added but are never removed. Consider whether this should be the case, or whether there should be a maximum, or whether old entries should be removed. Cases where there are specific potential problems will be flagged separately under a different issue.
There are 12 instances of this issue:
File: src/BranchPort.sol
131: bridgeAgentFactories.push(_bridgeAgentFactory);
323: bridgeAgents.push(_bridgeAgent);
342: bridgeAgentFactories.push(_newBridgeAgentFactory);
367: strategyTokens.push(_token);
388: portStrategies.push(_portStrategy);
421: bridgeAgents.push(_coreBranchBridgeAgent);
GitHub: 131, 323, 342, 367, 388, 421
File: src/RootPort.sol
136: bridgeAgentFactories.push(_bridgeAgentFactory);
385: bridgeAgents.push(_bridgeAgent);
424: bridgeAgentFactories.push(_bridgeAgentFactory);
File: src/factories/ERC20hTokenBranchFactory.sol
72: hTokens.push(newToken);
104: hTokens.push(newToken);
File: src/factories/ERC20hTokenRootFactory.sol
89: hTokens.push(newToken);
GitHub: 89
Note that there may be cases where a struct superficially appears to be used, but this is only because there are multiple definitions of the struct in different files. In such cases, the struct definition should be moved into a separate file. The instances below are the unused definitions.
There is one instance of this issue:
File: src/interfaces/IMulticall2.sol
15 struct Result {
16 bool success;
17 bytes returnData;
18: }
GitHub: 15
Note that there may be cases where an error superficially appears to be used, but this is only because there are multiple definitions of the error in different files. In such cases, the error definition should be moved into a separate file. The instances below are the unused definitions.
There are 7 instances of this issue:
File: src/interfaces/IBranchBridgeAgent.sol
348: error InsufficientGas();
GitHub: 348
File: src/interfaces/IRootBridgeAgent.sol
345: error GasErrorOrRepeatedTx();
349: error NotDao();
358: error UnrecognizedLocalBridgeAgent();
372: error InsufficientGasForFees();
376: error CallerIsNotPool();
377: error AmountsAreZero();
GitHub: 345, 349, 358, 372, 376, 377
e.g. @dev
or @notice
, and it must appear above the contract definition braces in order to be identified by the compiler as NatSpec
There are 4 instances of this issue:
File: src/ArbitrumBranchBridgeAgent.sol
10: library DeployArbitrumBranchBridgeAgent {
GitHub: 10
File: src/interfaces/ILayerZeroEndpoint.sol
7 interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
8 // @notice send a LayerZero message to the specified address at a LayerZero endpoint.
9 // @param _dstChainId - the destination chain identifier
10 // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
11 // @param _payload - a custom bytes payload to send to the destination contract
12 // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
13 // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
14: // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
GitHub: 7
File: src/interfaces/ILayerZeroReceiver.sol
5 interface ILayerZeroReceiver {
6 // @notice LayerZero endpoint will invoke this function to deliver the message on the destination
7 // @param _srcChainId - the source endpoint identifier
8 // @param _srcAddress - the source sending contract address from the source chain
9 // @param _nonce - the ordered message nonce
10: // @param _payload - the signed payload is the UA bytes has encoded to be sent
GitHub: 5
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
5 interface ILayerZeroUserApplicationConfig {
6 // @notice set the configuration of the LayerZero messaging library of the specified version
7 // @param _version - messaging library version
8 // @param _chainId - the chainId for the pending config change
9 // @param _configType - type of configuration. every messaging library has its own convention.
10: // @param _config - configuration in the bytes. can encode arbitrary content.
GitHub: 5
@notice
is used to explain to end users what the contract does, and the compiler interprets ///
or /**
comments as this tag if one wasn't explicitly provided
There are 4 instances of this issue:
File: src/ArbitrumBranchBridgeAgent.sol
10: library DeployArbitrumBranchBridgeAgent {
GitHub: 10
File: src/interfaces/ILayerZeroEndpoint.sol
7 interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
8 // @notice send a LayerZero message to the specified address at a LayerZero endpoint.
9 // @param _dstChainId - the destination chain identifier
10 // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
11 // @param _payload - a custom bytes payload to send to the destination contract
12 // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
13 // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
14: // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
GitHub: 7
File: src/interfaces/ILayerZeroReceiver.sol
5 interface ILayerZeroReceiver {
6 // @notice LayerZero endpoint will invoke this function to deliver the message on the destination
7 // @param _srcChainId - the source endpoint identifier
8 // @param _srcAddress - the source sending contract address from the source chain
9 // @param _nonce - the ordered message nonce
10: // @param _payload - the signed payload is the UA bytes has encoded to be sent
GitHub: 5
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
5 interface ILayerZeroUserApplicationConfig {
6 // @notice set the configuration of the LayerZero messaging library of the specified version
7 // @param _version - messaging library version
8 // @param _chainId - the chainId for the pending config change
9 // @param _configType - type of configuration. every messaging library has its own convention.
10: // @param _config - configuration in the bytes. can encode arbitrary content.
GitHub: 5
There are 90 instances of this issue:
see instances
File: src/CoreRootRouter.sol
520: error InvalidChainId();
522: error UnauthorizedChainId();
524: error UnauthorizedCallerNotManager();
526: error TokenAlreadyAdded();
528: error UnrecognizedGlobalToken();
530: error UnrecognizedBridgeAgentFactory();
GitHub: 520, 522, 524, 526, 528, 530
File: src/interfaces/IArbitrumBranchPort.sol
45: error UnknownGlobalToken();
46: error UnknownUnderlyingToken();
File: src/interfaces/IBranchBridgeAgent.sol
339: error UnknownFlag();
340: error ExecutionFailure();
342: error LayerZeroUnauthorizedCaller();
343: error LayerZeroUnauthorizedEndpoint();
345: error AlreadyExecutedTransaction();
347: error InvalidInput();
348: error InsufficientGas();
350: error NotDepositOwner();
351: error DepositRetryUnavailableUseCallout();
352: error DepositRedeemUnavailable();
354: error UnrecognizedRouter();
355: error UnrecognizedBridgeAgentExecutor();
GitHub: 339, 340, 342, 343, 345, 347, 348, 350, 351, 352, 354, 355
File: src/interfaces/IBranchPort.sol
245: error AlreadyAddedBridgeAgent();
246: error AlreadyAddedBridgeAgentFactory();
247: error InvalidMinimumReservesRatio();
248: error InvalidInputArrays();
249: error InsufficientReserves();
250: error UnrecognizedCore();
251: error UnrecognizedBridgeAgent();
252: error UnrecognizedBridgeAgentFactory();
253: error UnrecognizedPortStrategy();
254: error UnrecognizedStrategyToken();
255: error NotEnoughDebtToRepay();
GitHub: 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
File: src/interfaces/IBranchRouter.sol
113: error UnrecognizedFunctionId();
115: error UnrecognizedBridgeAgentExecutor();
File: src/interfaces/ICoreBranchRouter.sol
53: error UnrecognizedBridgeAgent();
54: error UnrecognizedBridgeAgentFactory();
File: src/interfaces/IERC20hTokenBranchFactory.sol
32: error UnrecognizedCoreRouter();
34: error UnrecognizedPort();
File: src/interfaces/IERC20hTokenRoot.sol
57: error UnrecognizedPort();
GitHub: 57
File: src/interfaces/IERC20hTokenRootFactory.sol
32: error UnrecognizedCoreRouterOrPort();
GitHub: 32
File: src/interfaces/IPortStrategy.sol
29: error UnrecognizedPort();
GitHub: 29
File: src/interfaces/IRootBridgeAgent.sol
344: error ExecutionFailure();
345: error GasErrorOrRepeatedTx();
346: error AlreadyExecutedTransaction();
347: error UnknownFlag();
349: error NotDao();
351: error LayerZeroUnauthorizedEndpoint();
352: error LayerZeroUnauthorizedCaller();
354: error AlreadyAddedBridgeAgent();
355: error UnrecognizedExecutor();
356: error UnrecognizedPort();
357: error UnrecognizedBridgeAgent();
358: error UnrecognizedLocalBridgeAgent();
359: error UnrecognizedBridgeAgentManager();
360: error UnrecognizedRouter();
362: error UnrecognizedUnderlyingAddress();
363: error UnrecognizedLocalAddress();
365: error SettlementRetryUnavailable();
366: error SettlementRetryUnavailableUseCallout();
367: error SettlementRedeemUnavailable();
368: error SettlementRetrieveUnavailable();
369: error NotSettlementOwner();
371: error InsufficientBalanceForSettlement();
372: error InsufficientGasForFees();
373: error InvalidInputParams();
374: error InvalidInputParamsLength();
376: error CallerIsNotPool();
377: error AmountsAreZero();
GitHub: 344, 345, 346, 347, 349, 351, 352, 354, 355, 356, 357, 358, 359, 360, 362, 363, 365, 366, 367, 368, 369, 371, 372, 373, 374, 376, 377
File: src/interfaces/IRootPort.sol
399: error InvalidGlobalAddress();
400: error InvalidLocalAddress();
401: error InvalidUnderlyingAddress();
403: error InvalidUserAddress();
405: error InvalidCoreRootRouter();
406: error InvalidCoreRootBridgeAgent();
407: error InvalidCoreBranchRouter();
408: error InvalidCoreBrancBridgeAgent();
410: error UnrecognizedBridgeAgentFactory();
411: error UnrecognizedBridgeAgent();
413: error UnrecognizedToken();
414: error UnableToMint();
416: error AlreadyAddedChain();
417: error AlreadyAddedEcosystemToken();
419: error AlreadyAddedBridgeAgent();
420: error AlreadyAddedBridgeAgentFactory();
421: error BridgeAgentNotAllowed();
422: error UnrecognizedCoreRootRouter();
423: error UnrecognizedLocalBranchPort();
GitHub: 399, 400, 401, 403, 405, 406, 407, 408, 410, 411, 413, 414, 416, 417, 419, 420, 421, 422, 423
File: src/interfaces/IRootRouter.sol
97: error UnrecognizedFunctionId();
98: error UnrecognizedBridgeAgentExecutor();
File: src/interfaces/IVirtualAccount.sol
79: error CallFailed();
81: error UnauthorizedCaller();
There are 28 instances of this issue:
File: src/interfaces/IBranchBridgeAgent.sol
332: event LogExecute(uint256 indexed nonce);
333: event LogFallback(uint256 indexed nonce);
File: src/interfaces/IBranchPort.sol
220: event DebtCreated(address indexed _strategy, address indexed _token, uint256 _amount);
221: event DebtRepaid(address indexed _strategy, address indexed _token, uint256 _amount);
223: event StrategyTokenAdded(address indexed _token, uint256 indexed _minimumReservesRatio);
224: event StrategyTokenToggled(address indexed _token);
226 event PortStrategyAdded(
227 address indexed _portStrategy, address indexed _token, uint256 indexed _dailyManagementLimit
228: );
229: event PortStrategyToggled(address indexed _portStrategy, address indexed _token);
230 event PortStrategyUpdated(
231 address indexed _portStrategy, address indexed _token, uint256 indexed _dailyManagementLimit
232: );
234: event BridgeAgentFactoryAdded(address indexed _bridgeAgentFactory);
235: event BridgeAgentFactoryToggled(address indexed _bridgeAgentFactory);
237: event BridgeAgentToggled(address indexed _bridgeAgent);
239: event CoreBranchSet(address indexed _coreBranchRouter, address indexed _coreBranchBridgeAgent);
GitHub: 220, 221, 223, 224, 226, 229, 230, 234, 235, 237, 239
File: src/interfaces/IRootBridgeAgent.sol
337: event LogExecute(uint256 indexed depositNonce, uint256 indexed srcChainId);
338: event LogFallback(uint256 indexed settlementNonce, uint256 indexed dstChainId);
File: src/interfaces/IRootPort.sol
371: event BridgeAgentFactoryAdded(address indexed bridgeAgentFactory);
372: event BridgeAgentFactoryToggled(address indexed bridgeAgentFactory);
374: event BridgeAgentAdded(address indexed bridgeAgent, address indexed manager);
375: event BridgeAgentToggled(address indexed bridgeAgent);
376: event BridgeAgentSynced(address indexed bridgeAgent, address indexed rootBridgeAgent, uint256 indexed srcChainId);
378: event NewChainAdded(uint256 indexed chainId);
380: event VirtualAccountCreated(address indexed user, address account);
382 event LocalTokenAdded(
383 address indexed underlyingAddress, address indexed localAddress, address indexed globalAddress, uint256 chainId
384: );
385: event GlobalTokenAdded(address indexed localAddress, address indexed globalAddress, uint256 indexed chainId);
386: event EcosystemTokenAdded(address indexed ecoTokenGlobalAddress);
387: event CoreRootSet(address indexed coreRootRouter, address indexed coreRootBridgeAgent);
388 event CoreBranchSet(
389 address indexed coreBranchRouter, address indexed coreBranchBridgeAgent, uint16 indexed dstChainId
390: );
391 event CoreBranchSynced(
392 address indexed coreBranchRouter, address indexed coreBranchBridgeAgent, uint16 indexed dstChainId
393: );
GitHub: 371, 372, 374, 375, 376, 378, 380, 382, 385, 386, 387, 388, 391
e.g. @notice
for public state variables, and @dev
for non-public ones
There are 22 instances of this issue:
File: src/BranchPort.sol
97: uint256 internal constant DIVISIONER = 1e4;
98: uint256 internal constant MIN_RESERVE_RATIO = 3e3;
File: src/interfaces/BridgeAgentConstants.sol
13: uint8 internal constant STATUS_READY = 0;
15: uint8 internal constant STATUS_DONE = 1;
17: uint8 internal constant STATUS_RETRIEVE = 2;
21: uint8 internal constant STATUS_FAILED = 1;
23: uint8 internal constant STATUS_SUCCESS = 0;
27: uint256 internal constant PARAMS_START = 1;
29: uint256 internal constant PARAMS_START_SIGNED = 21;
31: uint256 internal constant PARAMS_TKN_START = 5;
33: uint256 internal constant PARAMS_TKN_START_SIGNED = 25;
35: uint256 internal constant PARAMS_ENTRY_SIZE = 32;
37: uint256 internal constant PARAMS_ADDRESS_SIZE = 20;
39: uint256 internal constant PARAMS_TKN_SET_SIZE = 109;
41: uint256 internal constant PARAMS_TKN_SET_SIZE_MULTIPLE = 128;
43: uint256 internal constant ADDRESS_END_OFFSET = 12;
45: uint256 internal constant PARAMS_AMT_OFFSET = 64;
47: uint256 internal constant PARAMS_DEPOSIT_OFFSET = 96;
49: uint256 internal constant PARAMS_END_OFFSET = 6;
51: uint256 internal constant PARAMS_END_SIGNED_OFFSET = 26;
53: uint256 internal constant PARAMS_SETTLEMENT_OFFSET = 129;
57: uint256 internal constant MAX_TOKENS_LENGTH = 255;
GitHub: 13, 15, 17, 21, 23, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 57
There are 37 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
11 function deploy(uint16 _localChainId, address _daoAddress, address _localRouterAddress, address _localPortAddress)
12 external
13 returns (ArbitrumBranchBridgeAgent)
14: {
GitHub: 11
File: src/BaseBranchRouter.sol
48: constructor() {
GitHub: 48
File: src/BranchBridgeAgent.sol
24 function deploy(
25 uint16 _rootChainId,
26 uint16 _localChainId,
27 address _rootBridgeAgentAddress,
28 address _lzEndpointAddress,
29 address _localRouterAddress,
30 address _localPortAddress
31: ) external returns (BranchBridgeAgent) {
149: receive() external payable {}
File: src/BranchBridgeAgentExecutor.sol
16: function deploy() external returns (address) {
GitHub: 16
File: src/CoreRootRouter.sol
83: function initialize(address _bridgeAgentAddress, address _hTokenFactory) external onlyOwner {
GitHub: 83
File: src/MulticallRootRouterLibZip.sol
29 constructor(uint256 _localChainId, address _localPortAddress, address _multicallAddress)
30 MulticallRootRouter(_localChainId, _localPortAddress, _multicallAddress)
31: {}
GitHub: 29
File: src/RootBridgeAgent.sol
128: receive() external payable {}
GitHub: 128
File: src/RootBridgeAgentExecutor.sol
14: function deploy(address _rootBridgeAgent) external returns (address) {
GitHub: 14
File: src/RootPort.sol
304 function bridgeToLocalBranchFromRoot(address _to, address _hToken, uint256 _amount)
305 external
306 override
307 requiresLocalBranchPort
308: {
GitHub: 304
File: src/VirtualAccount.sol
44: receive() external payable {}
GitHub: 44
File: src/interfaces/ILayerZeroEndpoint.sol
15 function send(
16 uint16 _dstChainId,
17 bytes calldata _destination,
18 bytes calldata _payload,
19 address payable _refundAddress,
20 address _zroPaymentAddress,
21 bytes calldata _adapterParams
22: ) external payable;
31 function receivePayload(
32 uint16 _srcChainId,
33 bytes calldata _srcAddress,
34 address _dstAddress,
35 uint64 _nonce,
36 uint256 _gasLimit,
37 bytes calldata _payload
38: ) external;
43: function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);
47: function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);
55 function estimateFees(
56 uint16 _dstChainId,
57 address _userApplication,
58 bytes calldata _payload,
59 bool _payInZRO,
60 bytes calldata _adapterParam
61: ) external view returns (uint256 nativeFee, uint256 zroFee);
64: function getChainId() external view returns (uint16);
70: function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;
75: function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);
79: function getSendLibraryAddress(address _userApplication) external view returns (address);
83: function getReceiveLibraryAddress(address _userApplication) external view returns (address);
87: function isSendingPayload() external view returns (bool);
91: function isReceivingPayload() external view returns (bool);
98 function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint256 _configType)
99 external
100 view
101: returns (bytes memory);
105: function getSendVersion(address _userApplication) external view returns (uint16);
109: function getReceiveVersion(address _userApplication) external view returns (uint16);
GitHub: 15, 31, 43, 47, 55, 64, 70, 75, 79, 83, 87, 91, 98, 105, 109
File: src/interfaces/ILayerZeroReceiver.sol
11: function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;
GitHub: 11
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
11: function setConfig(uint16 _version, uint16 _chainId, uint256 _configType, bytes calldata _config) external;
15: function setSendVersion(uint16 _version) external;
19: function setReceiveVersion(uint16 _version) external;
24: function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;
File: src/interfaces/IMulticall2.sol
20: function aggregate(Call[] memory calls) external returns (uint256 blockNumber, bytes[] memory returnData);
GitHub: 20
File: src/interfaces/IRootBridgeAgentFactory.sol
16: function createBridgeAgent(address newRootRouterAddress) external returns (address newBridgeAgent);
GitHub: 16
File: src/interfaces/IRootPort.sol
11: function bridgeAgentAddress() external view returns (address);
12: function hTokenFactoryAddress() external view returns (address);
13 function setCoreBranch(
14 address _refundee,
15 address _coreBranchRouter,
16 address _coreBranchBridgeAgent,
17 uint16 _dstChainId,
18 GasParams calldata _gParams
19: ) external payable;
File: src/token/ERC20hTokenBranch.sol
13 constructor(
14 string memory chainName,
15 string memory chainSymbol,
16 string memory _name,
17 string memory _symbol,
18 uint8 _decimals,
19 address _owner
20: ) ERC20(string(string.concat(chainName, _name)), string(string.concat(chainSymbol, _symbol)), _decimals) {
GitHub: 13
@notice
is used to explain to end users what the function does, and the compiler interprets ///
or /**
comments as this tag if one wasn't explicitly provided
There are 37 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
11 function deploy(uint16 _localChainId, address _daoAddress, address _localRouterAddress, address _localPortAddress)
12 external
13 returns (ArbitrumBranchBridgeAgent)
14: {
GitHub: 11
File: src/BaseBranchRouter.sol
48: constructor() {
GitHub: 48
File: src/BranchBridgeAgent.sol
24 function deploy(
25 uint16 _rootChainId,
26 uint16 _localChainId,
27 address _rootBridgeAgentAddress,
28 address _lzEndpointAddress,
29 address _localRouterAddress,
30 address _localPortAddress
31: ) external returns (BranchBridgeAgent) {
149: receive() external payable {}
File: src/BranchBridgeAgentExecutor.sol
16: function deploy() external returns (address) {
GitHub: 16
File: src/CoreRootRouter.sol
83: function initialize(address _bridgeAgentAddress, address _hTokenFactory) external onlyOwner {
GitHub: 83
File: src/MulticallRootRouterLibZip.sol
29 constructor(uint256 _localChainId, address _localPortAddress, address _multicallAddress)
30 MulticallRootRouter(_localChainId, _localPortAddress, _multicallAddress)
31: {}
GitHub: 29
File: src/RootBridgeAgent.sol
128: receive() external payable {}
GitHub: 128
File: src/RootBridgeAgentExecutor.sol
14: function deploy(address _rootBridgeAgent) external returns (address) {
GitHub: 14
File: src/RootPort.sol
304 function bridgeToLocalBranchFromRoot(address _to, address _hToken, uint256 _amount)
305 external
306 override
307 requiresLocalBranchPort
308: {
GitHub: 304
File: src/VirtualAccount.sol
44: receive() external payable {}
GitHub: 44
File: src/interfaces/ILayerZeroEndpoint.sol
15 function send(
16 uint16 _dstChainId,
17 bytes calldata _destination,
18 bytes calldata _payload,
19 address payable _refundAddress,
20 address _zroPaymentAddress,
21 bytes calldata _adapterParams
22: ) external payable;
31 function receivePayload(
32 uint16 _srcChainId,
33 bytes calldata _srcAddress,
34 address _dstAddress,
35 uint64 _nonce,
36 uint256 _gasLimit,
37 bytes calldata _payload
38: ) external;
43: function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);
47: function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);
55 function estimateFees(
56 uint16 _dstChainId,
57 address _userApplication,
58 bytes calldata _payload,
59 bool _payInZRO,
60 bytes calldata _adapterParam
61: ) external view returns (uint256 nativeFee, uint256 zroFee);
64: function getChainId() external view returns (uint16);
70: function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;
75: function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);
79: function getSendLibraryAddress(address _userApplication) external view returns (address);
83: function getReceiveLibraryAddress(address _userApplication) external view returns (address);
87: function isSendingPayload() external view returns (bool);
91: function isReceivingPayload() external view returns (bool);
98 function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint256 _configType)
99 external
100 view
101: returns (bytes memory);
105: function getSendVersion(address _userApplication) external view returns (uint16);
109: function getReceiveVersion(address _userApplication) external view returns (uint16);
GitHub: 15, 31, 43, 47, 55, 64, 70, 75, 79, 83, 87, 91, 98, 105, 109
File: src/interfaces/ILayerZeroReceiver.sol
11: function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;
GitHub: 11
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
11: function setConfig(uint16 _version, uint16 _chainId, uint256 _configType, bytes calldata _config) external;
15: function setSendVersion(uint16 _version) external;
19: function setReceiveVersion(uint16 _version) external;
24: function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;
File: src/interfaces/IMulticall2.sol
20: function aggregate(Call[] memory calls) external returns (uint256 blockNumber, bytes[] memory returnData);
GitHub: 20
File: src/interfaces/IRootBridgeAgentFactory.sol
16: function createBridgeAgent(address newRootRouterAddress) external returns (address newBridgeAgent);
GitHub: 16
File: src/interfaces/IRootPort.sol
11: function bridgeAgentAddress() external view returns (address);
12: function hTokenFactoryAddress() external view returns (address);
13 function setCoreBranch(
14 address _refundee,
15 address _coreBranchRouter,
16 address _coreBranchBridgeAgent,
17 uint16 _dstChainId,
18 GasParams calldata _gParams
19: ) external payable;
File: src/token/ERC20hTokenBranch.sol
13 constructor(
14 string memory chainName,
15 string memory chainSymbol,
16 string memory _name,
17 string memory _symbol,
18 uint8 _decimals,
19 address _owner
20: ) ERC20(string(string.concat(chainName, _name)), string(string.concat(chainSymbol, _symbol)), _decimals) {
GitHub: 13
Doing so will prevent typo bugs
There are 62 instances of this issue:
see instances
File: src/ArbitrumCoreBranchRouter.sol
127: if (_data[0] == 0x02) {
146: } else if (_data[0] == 0x03) {
152: } else if (_data[0] == 0x04) {
157: } else if (_data[0] == 0x05) {
162: } else if (_data[0] == 0x06) {
GitHub: 127, 146, 152, 157, 162
File: src/BaseBranchRouter.sol
213: require(_unlocked == 1);
GitHub: 213
File: src/BranchBridgeAgent.sol
359: if (uint8(deposit.hTokens.length) == 1) {
412: if (payload.length == 0) revert DepositRetryUnavailableUseCallout();
599: if (flag == 0x00) {
616: } else if (flag == 0x01) {
638: } else if (flag == 0x02) {
663: } else if (flag == 0x03) {
681: } else if (flag == 0x04) {
651: _payload[0] == 0x82,
629: _payload[0] == 0x81,
923: require(_unlocked == 1);
942: if (_srcAddress.length != 40) revert LayerZeroUnauthorizedCaller();
GitHub: 359, 412, 599, 616, 638, 663, 681, 651, 629, 923, 942
File: src/BranchPort.sol
487: if (block.timestamp - lastManaged[msg.sender][_token] >= 1 days) {
567: require(_unlocked == 1);
File: src/CoreBranchRouter.sol
88: if (_params[0] == 0x01) {
100: } else if (_params[0] == 0x02) {
115: } else if (_params[0] == 0x03) {
121: } else if (_params[0] == 0x04) {
127: } else if (_params[0] == 0x05) {
133: } else if (_params[0] == 0x06) {
140: } else if (_params[0] == 0x07) {
GitHub: 88, 100, 115, 121, 127, 133, 140
File: src/CoreRootRouter.sol
307: if (funcId == 0x02) {
314: } else if (funcId == 0x03) {
320: } else if (funcId == 0x04) {
337: if (funcId == 0x01) {
File: src/MulticallRootRouter.sol
142: if (funcId == 0x01) {
150: } else if (funcId == 0x02) {
174: } else if (funcId == 0x03) {
234: if (funcId == 0x01) {
242: } else if (funcId == 0x02) {
265: } else if (funcId == 0x03) {
323: if (funcId == 0x01) {
331: } else if (funcId == 0x02) {
354: } else if (funcId == 0x03) {
411: if (funcId == 0x01) {
419: } else if (funcId == 0x02) {
442: } else if (funcId == 0x03) {
591: require(_unlocked == 1);
GitHub: 142, 150, 174, 234, 242, 265, 323, 331, 354, 411, 419, 442, 591
File: src/RootBridgeAgent.sol
444: if (_payload[0] == 0x00) {
467: } else if (_payload[0] == 0x01) {
490: } else if (_payload[0] == 0x02) {
513: } else if (_payload[0] == 0x03) {
539: } else if (_payload[0] == 0x04) {
577: } else if (_payload[0] & 0x7F == 0x05) {
617: } else if (_payload[0] & 0x7F == 0x06) {
657: } else if (_payload[0] & 0x7F == 0x07) {
699: } else if (_payload[0] == 0x08) {
718: } else if (_payload[0] == 0x09) {
684: _payload[0] == 0x87,
640: _payload[0] == 0x86,
600: _payload[0] == 0x85,
871: if (_hTokens.length == 0) revert SettlementRetryUnavailableUseCallout();
877: if (_hTokens.length == 1) {
1141: if (_amount == 0 && _deposit == 0) revert InvalidInputParams();
1191: require(_unlocked == 1);
1210: if (_srcAddress.length != 40) revert LayerZeroUnauthorizedCaller();
GitHub: 444, 467, 490, 513, 539, 577, 617, 657, 699, 718, 684, 640, 600, 871, 877, 1141, 1141, 1191, 1210
Consider adding parameters to the error to indicate which user or values caused the failure
There are 90 instances of this issue:
see instances
File: src/CoreRootRouter.sol
520: error InvalidChainId();
522: error UnauthorizedChainId();
524: error UnauthorizedCallerNotManager();
526: error TokenAlreadyAdded();
528: error UnrecognizedGlobalToken();
530: error UnrecognizedBridgeAgentFactory();
GitHub: 520, 522, 524, 526, 528, 530
File: src/interfaces/IArbitrumBranchPort.sol
45: error UnknownGlobalToken();
46: error UnknownUnderlyingToken();
File: src/interfaces/IBranchBridgeAgent.sol
339: error UnknownFlag();
340: error ExecutionFailure();
342: error LayerZeroUnauthorizedCaller();
343: error LayerZeroUnauthorizedEndpoint();
345: error AlreadyExecutedTransaction();
347: error InvalidInput();
348: error InsufficientGas();
350: error NotDepositOwner();
351: error DepositRetryUnavailableUseCallout();
352: error DepositRedeemUnavailable();
354: error UnrecognizedRouter();
355: error UnrecognizedBridgeAgentExecutor();
GitHub: 339, 340, 342, 343, 345, 347, 348, 350, 351, 352, 354, 355
File: src/interfaces/IBranchPort.sol
245: error AlreadyAddedBridgeAgent();
246: error AlreadyAddedBridgeAgentFactory();
247: error InvalidMinimumReservesRatio();
248: error InvalidInputArrays();
249: error InsufficientReserves();
250: error UnrecognizedCore();
251: error UnrecognizedBridgeAgent();
252: error UnrecognizedBridgeAgentFactory();
253: error UnrecognizedPortStrategy();
254: error UnrecognizedStrategyToken();
255: error NotEnoughDebtToRepay();
GitHub: 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
File: src/interfaces/IBranchRouter.sol
113: error UnrecognizedFunctionId();
115: error UnrecognizedBridgeAgentExecutor();
File: src/interfaces/ICoreBranchRouter.sol
53: error UnrecognizedBridgeAgent();
54: error UnrecognizedBridgeAgentFactory();
File: src/interfaces/IERC20hTokenBranchFactory.sol
32: error UnrecognizedCoreRouter();
34: error UnrecognizedPort();
File: src/interfaces/IERC20hTokenRoot.sol
57: error UnrecognizedPort();
GitHub: 57
File: src/interfaces/IERC20hTokenRootFactory.sol
32: error UnrecognizedCoreRouterOrPort();
GitHub: 32
File: src/interfaces/IPortStrategy.sol
29: error UnrecognizedPort();
GitHub: 29
File: src/interfaces/IRootBridgeAgent.sol
344: error ExecutionFailure();
345: error GasErrorOrRepeatedTx();
346: error AlreadyExecutedTransaction();
347: error UnknownFlag();
349: error NotDao();
351: error LayerZeroUnauthorizedEndpoint();
352: error LayerZeroUnauthorizedCaller();
354: error AlreadyAddedBridgeAgent();
355: error UnrecognizedExecutor();
356: error UnrecognizedPort();
357: error UnrecognizedBridgeAgent();
358: error UnrecognizedLocalBridgeAgent();
359: error UnrecognizedBridgeAgentManager();
360: error UnrecognizedRouter();
362: error UnrecognizedUnderlyingAddress();
363: error UnrecognizedLocalAddress();
365: error SettlementRetryUnavailable();
366: error SettlementRetryUnavailableUseCallout();
367: error SettlementRedeemUnavailable();
368: error SettlementRetrieveUnavailable();
369: error NotSettlementOwner();
371: error InsufficientBalanceForSettlement();
372: error InsufficientGasForFees();
373: error InvalidInputParams();
374: error InvalidInputParamsLength();
376: error CallerIsNotPool();
377: error AmountsAreZero();
GitHub: 344, 345, 346, 347, 349, 351, 352, 354, 355, 356, 357, 358, 359, 360, 362, 363, 365, 366, 367, 368, 369, 371, 372, 373, 374, 376, 377
File: src/interfaces/IRootPort.sol
399: error InvalidGlobalAddress();
400: error InvalidLocalAddress();
401: error InvalidUnderlyingAddress();
403: error InvalidUserAddress();
405: error InvalidCoreRootRouter();
406: error InvalidCoreRootBridgeAgent();
407: error InvalidCoreBranchRouter();
408: error InvalidCoreBrancBridgeAgent();
410: error UnrecognizedBridgeAgentFactory();
411: error UnrecognizedBridgeAgent();
413: error UnrecognizedToken();
414: error UnableToMint();
416: error AlreadyAddedChain();
417: error AlreadyAddedEcosystemToken();
419: error AlreadyAddedBridgeAgent();
420: error AlreadyAddedBridgeAgentFactory();
421: error BridgeAgentNotAllowed();
422: error UnrecognizedCoreRootRouter();
423: error UnrecognizedLocalBranchPort();
GitHub: 399, 400, 401, 403, 405, 406, 407, 408, 410, 411, 413, 414, 416, 417, 419, 420, 421, 422, 423
File: src/interfaces/IRootRouter.sol
97: error UnrecognizedFunctionId();
98: error UnrecognizedBridgeAgentExecutor();
File: src/interfaces/IVirtualAccount.sol
79: error CallFailed();
81: error UnauthorizedCaller();
There are 9 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
10: library DeployArbitrumBranchBridgeAgent {
GitHub: 10
File: src/BranchBridgeAgent.sol
23: library DeployBranchBridgeAgent {
GitHub: 23
File: src/BranchBridgeAgentExecutor.sol
15: library DeployBranchBridgeAgentExecutor {
GitHub: 15
File: src/RootBridgeAgentExecutor.sol
13: library DeployRootBridgeAgentExecutor {
GitHub: 13
File: src/VirtualAccount.sol
17: contract VirtualAccount is IVirtualAccount, ERC1155Receiver {
GitHub: 17
File: src/interfaces/ILayerZeroEndpoint.sol
7 interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
8 // @notice send a LayerZero message to the specified address at a LayerZero endpoint.
9 // @param _dstChainId - the destination chain identifier
10 // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
11 // @param _payload - a custom bytes payload to send to the destination contract
12 // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
13 // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
14: // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
GitHub: 7
File: src/interfaces/ILayerZeroReceiver.sol
5 interface ILayerZeroReceiver {
6 // @notice LayerZero endpoint will invoke this function to deliver the message on the destination
7 // @param _srcChainId - the source endpoint identifier
8 // @param _srcAddress - the source sending contract address from the source chain
9 // @param _nonce - the ordered message nonce
10: // @param _payload - the signed payload is the UA bytes has encoded to be sent
GitHub: 5
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
5 interface ILayerZeroUserApplicationConfig {
6 // @notice set the configuration of the LayerZero messaging library of the specified version
7 // @param _version - messaging library version
8 // @param _chainId - the chainId for the pending config change
9 // @param _configType - type of configuration. every messaging library has its own convention.
10: // @param _config - configuration in the bytes. can encode arbitrary content.
GitHub: 5
File: src/interfaces/IRootPort.sol
10: interface ICoreRootRouter {
GitHub: 10
@dev
is used to explain extra details to developers
There are 34 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
10: library DeployArbitrumBranchBridgeAgent {
31 contract ArbitrumBranchBridgeAgent is BranchBridgeAgent {
32 /*///////////////////////////////////////////////////////////////
33 CONSTRUCTOR
34 //////////////////////////////////////////////////////////////*/
35
36 /**
37 * @notice Constructor for Arbitrum Branch Bridge Agent.
38 * @param _localChainId Local Chain Layer Zero Id.
39 * @param _rootBridgeAgentAddress Root Bridge Agent Address.
40 * @param _localRouterAddress Local Core Branch Router Address.
41 * @param _localPortAddress Local Branch Port Address.
42: */
File: src/ArbitrumBranchPort.sol
14: contract ArbitrumBranchPort is BranchPort, IArbitrumBranchPort {
GitHub: 14
File: src/BaseBranchRouter.sol
25: contract BaseBranchRouter is IBranchRouter, Ownable {
GitHub: 25
File: src/BranchBridgeAgent.sol
23: library DeployBranchBridgeAgent {
45: contract BranchBridgeAgent is IBranchBridgeAgent, BridgeAgentConstants {
File: src/BranchBridgeAgentExecutor.sol
15: library DeployBranchBridgeAgentExecutor {
GitHub: 15
File: src/BranchPort.sol
17: contract BranchPort is Ownable, IBranchPort {
GitHub: 17
File: src/CoreBranchRouter.sol
18 contract CoreBranchRouter is ICoreBranchRouter, BaseBranchRouter {
19: /// @notice hToken Factory Address.
GitHub: 18
File: src/RootBridgeAgent.sol
32: contract RootBridgeAgent is IRootBridgeAgent, BridgeAgentConstants {
GitHub: 32
File: src/RootBridgeAgentExecutor.sol
13: library DeployRootBridgeAgentExecutor {
GitHub: 13
File: src/RootPort.sol
16: contract RootPort is Ownable, IRootPort {
GitHub: 16
File: src/VirtualAccount.sol
17: contract VirtualAccount is IVirtualAccount, ERC1155Receiver {
GitHub: 17
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
17 contract ArbitrumBranchBridgeAgentFactory is BranchBridgeAgentFactory {
18 /*///////////////////////////////////////////////////////////////
19 CONSTRUCTOR
20 //////////////////////////////////////////////////////////////*/
21
22 /**
23 * @notice Constructor for Bridge Agent Factory Contract.
24 * @param _rootChainId Root Chain Layer Zero Id.
25 * @param _rootBridgeAgentFactoryAddress Root Bridge Agent Factory Address.
26 * @param _localCoreBranchRouterAddress Local Core Branch Router Address.
27 * @param _localPortAddress Local Branch Port Address.
28 * @param _owner Owner of the contract.
29: */
GitHub: 17
File: src/factories/BranchBridgeAgentFactory.sol
19 contract BranchBridgeAgentFactory is Ownable, IBranchBridgeAgentFactory {
20: /// @notice Local Chain Id.
GitHub: 19
File: src/factories/ERC20hTokenBranchFactory.sol
12 contract ERC20hTokenBranchFactory is Ownable, IERC20hTokenBranchFactory {
13: /// @notice Local Network Identifier.
GitHub: 12
File: src/factories/ERC20hTokenRootFactory.sol
12 contract ERC20hTokenRootFactory is Ownable, IERC20hTokenRootFactory {
13: /// @notice Local Network Identifier.
GitHub: 12
File: src/factories/RootBridgeAgentFactory.sol
11 contract RootBridgeAgentFactory is IRootBridgeAgentFactory {
12: /// @notice Root Chain Id
GitHub: 11
File: src/interfaces/IArbitrumBranchPort.sol
16 interface IArbitrumBranchPort is IBranchPort {
17 /*///////////////////////////////////////////////////////////////
18 EXTERNAL FUNCTIONS
19 //////////////////////////////////////////////////////////////*/
20
21 /**
22 * @notice Function to deposit underlying/native token amount into Port in exchange for Local hToken.
23 * @param _depositor underlying/native token depositor.
24 * @param _recipient hToken receiver.
25 * @param _underlyingAddress underlying/native token address.
26 * @param _amount amount of tokens.
27: */
GitHub: 16
File: src/interfaces/IBranchBridgeAgentFactory.sol
12 interface IBranchBridgeAgentFactory {
13 /*///////////////////////////////////////////////////////////////
14 BRIDGE AGENT FUNCTIONS
15 //////////////////////////////////////////////////////////////*/
16
17 /**
18 * @notice Creates a new Branch Bridge Agent.
19 * @param newRootRouterAddress New Root Router Address.
20 * @param rootBridgeAgentAddress Root Bridge Agent Address.
21 * @param _rootBridgeAgentFactoryAddress Root Bridge Agent Factory Address.
22 * @return newBridgeAgent New Bridge Agent Address.
23: */
GitHub: 12
File: src/interfaces/IBranchPort.sol
14 interface IBranchPort {
15 /*///////////////////////////////////////////////////////////////
16 VIEW FUNCTIONS
17 //////////////////////////////////////////////////////////////*/
18 /**
19 * @notice Returns true if the address is a Bridge Agent.
20 * @param _bridgeAgent Bridge Agent address.
21 * @return bool.
22: */
GitHub: 14
File: src/interfaces/IBranchRouter.sol
21 interface IBranchRouter {
22 /*///////////////////////////////////////////////////////////////
23 VIEW / STATE
24 //////////////////////////////////////////////////////////////*/
25
26: /// @notice External function to return the Branch Chain's Local Port Address.
GitHub: 21
File: src/interfaces/IERC20hTokenBranch.sol
11 interface IERC20hTokenBranch {
12 /*///////////////////////////////////////////////////////////////
13 ERC20 LOGIC
14 //////////////////////////////////////////////////////////////*/
15
16 /**
17 * @notice Function to mint tokens in the Branch Chain.
18 * @param account Address of the account to receive the tokens.
19 * @param amount Amount of tokens to be minted.
20 * @return Boolean indicating if the operation was successful.
21: */
GitHub: 11
File: src/interfaces/ILayerZeroEndpoint.sol
7 interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
8 // @notice send a LayerZero message to the specified address at a LayerZero endpoint.
9 // @param _dstChainId - the destination chain identifier
10 // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
11 // @param _payload - a custom bytes payload to send to the destination contract
12 // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
13 // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
14: // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
GitHub: 7
File: src/interfaces/ILayerZeroReceiver.sol
5 interface ILayerZeroReceiver {
6 // @notice LayerZero endpoint will invoke this function to deliver the message on the destination
7 // @param _srcChainId - the source endpoint identifier
8 // @param _srcAddress - the source sending contract address from the source chain
9 // @param _nonce - the ordered message nonce
10: // @param _payload - the signed payload is the UA bytes has encoded to be sent
GitHub: 5
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
5 interface ILayerZeroUserApplicationConfig {
6 // @notice set the configuration of the LayerZero messaging library of the specified version
7 // @param _version - messaging library version
8 // @param _chainId - the chainId for the pending config change
9 // @param _configType - type of configuration. every messaging library has its own convention.
10: // @param _config - configuration in the bytes. can encode arbitrary content.
GitHub: 5
File: src/interfaces/IMulticall2.sol
9: interface IMulticall2 {
GitHub: 9
File: src/interfaces/IPortStrategy.sol
12 interface IPortStrategy {
13 /*///////////////////////////////////////////////////////////////
14 TOKEN MANAGEMENT
15 //////////////////////////////////////////////////////////////*/
16
17 /**
18 * @notice Function to withdraw underlying/native token amount back into Branch Port.
19 * @param _recipient hToken receiver.
20 * @param _token native token address.
21 * @param _amount amount of tokens.
22: */
GitHub: 12
File: src/interfaces/IRootBridgeAgentFactory.sol
11 interface IRootBridgeAgentFactory {
12 /*///////////////////////////////////////////////////////////////
13 BRIDGE AGENT FUNCTIONS
14 //////////////////////////////////////////////////////////////*/
15:
GitHub: 11
File: src/interfaces/IRootPort.sol
10: interface ICoreRootRouter {
31 interface IRootPort {
32 /*///////////////////////////////////////////////////////////////
33 VIEW FUNCTIONS
34 //////////////////////////////////////////////////////////////*/
35 /**
36 * @notice View Function returns True if the chain Id has been added to the system.
37 * @param _chainId The Layer Zero chainId of the chain.
38 * @return bool True if the chain Id has been added to the system.
39: */
File: src/interfaces/IRootRouter.sol
14 interface IRootRouter {
15 /*///////////////////////////////////////////////////////////////
16 LAYERZERO FUNCTIONS
17 ///////////////////////////////////////////////////////////////*/
18
19 /**
20 * @notice Function to execute Branch Bridge Agent system initiated requests with no asset deposit.
21 * @param params data received from messaging layer.
22 * @param srcChainId chain where the request originated from.
23 *
24: */
GitHub: 14
File: src/token/ERC20hTokenBranch.sol
12: contract ERC20hTokenBranch is ERC20, Ownable, IERC20hTokenBranch {
GitHub: 12
File: src/token/ERC20hTokenRoot.sol
12 contract ERC20hTokenRoot is ERC20, Ownable, IERC20hTokenRoot {
13: /// @inheritdoc IERC20hTokenRoot
GitHub: 12
There are 4 instances of this issue:
File: src/ArbitrumBranchBridgeAgent.sol
10: library DeployArbitrumBranchBridgeAgent {
GitHub: 10
File: src/interfaces/ILayerZeroEndpoint.sol
7 interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
8 // @notice send a LayerZero message to the specified address at a LayerZero endpoint.
9 // @param _dstChainId - the destination chain identifier
10 // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
11 // @param _payload - a custom bytes payload to send to the destination contract
12 // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
13 // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
14: // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
GitHub: 7
File: src/interfaces/ILayerZeroReceiver.sol
5 interface ILayerZeroReceiver {
6 // @notice LayerZero endpoint will invoke this function to deliver the message on the destination
7 // @param _srcChainId - the source endpoint identifier
8 // @param _srcAddress - the source sending contract address from the source chain
9 // @param _nonce - the ordered message nonce
10: // @param _payload - the signed payload is the UA bytes has encoded to be sent
GitHub: 5
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
5 interface ILayerZeroUserApplicationConfig {
6 // @notice set the configuration of the LayerZero messaging library of the specified version
7 // @param _version - messaging library version
8 // @param _chainId - the chainId for the pending config change
9 // @param _configType - type of configuration. every messaging library has its own convention.
10: // @param _config - configuration in the bytes. can encode arbitrary content.
GitHub: 5
Consider adding a comment about why the function body is empty
There is one instance of this issue:
File: src/MulticallRootRouterLibZip.sol
29 constructor(uint256 _localChainId, address _localPortAddress, address _multicallAddress)
30 MulticallRootRouter(_localChainId, _localPortAddress, _multicallAddress)
31: {}
GitHub: 29
Starting with version 0.8.4, Solidity has the bytes.concat()
function, which allows one to concatenate a list of bytes/strings, without extra padding. Using this function rather than abi.encodePacked()
makes the intended operation more clear, leading to less reviewer confusion.
There are 14 instances of this issue:
File: src/ArbitrumCoreBranchRouter.sol
62: bytes memory payload = abi.encodePacked(bytes1(0x02), params);
115: bytes memory payload = abi.encodePacked(bytes1(0x04), data);
File: src/BranchBridgeAgent.sol
474: bytes memory payload = abi.encodePacked(_hasFallbackToggled ? bytes1(0x87) : bytes1(0x07), params);
GitHub: 474
File: src/CoreBranchRouter.sol
51: bytes memory payload = abi.encodePacked(bytes1(0x01), params);
75: bytes memory payload = abi.encodePacked(bytes1(0x02), params);
181: bytes memory payload = abi.encodePacked(bytes1(0x03), params);
229: bytes memory payload = abi.encodePacked(bytes1(0x04), params);
File: src/CoreRootRouter.sol
136: bytes memory payload = abi.encodePacked(bytes1(0x02), params);
171: bytes memory payload = abi.encodePacked(bytes1(0x03), params);
196: bytes memory payload = abi.encodePacked(bytes1(0x04), params);
223: bytes memory payload = abi.encodePacked(bytes1(0x05), params);
254: bytes memory payload = abi.encodePacked(bytes1(0x06), params);
284: bytes memory payload = abi.encodePacked(bytes1(0x07), params);
434: bytes memory payload = abi.encodePacked(bytes1(0x01), params);
GitHub: 136, 171, 196, 223, 254, 284, 434
The code can be made more compact while also increasing readability by converting the following if
-statements to ternaries (e.g. foo += (x > y) ? a : b
)
There are 2 instances of this issue:
File: src/BranchBridgeAgent.sol
384 if (_isSigned) {
385 //Pack new Data
386 payload = abi.encodePacked(
387 _hasFallbackToggled ? bytes1(0x86) : bytes1(0x06),
388 msg.sender,
389 uint8(deposit.hTokens.length),
390 _depositNonce,
391 deposit.hTokens,
392 deposit.tokens,
393 deposit.amounts,
394 deposit.deposits,
395 _params
396 );
397 } else {
398 payload = abi.encodePacked(
399 bytes1(0x03),
400 uint8(deposit.hTokens.length),
401 _depositNonce,
402 deposit.hTokens,
403 deposit.tokens,
404 deposit.amounts,
405 deposit.deposits,
406 _params
407 );
408: }
360 if (_isSigned) {
361 //Pack new Data
362 payload = abi.encodePacked(
363 _hasFallbackToggled ? bytes1(0x85) : bytes1(0x05),
364 msg.sender,
365 _depositNonce,
366 deposit.hTokens[0],
367 deposit.tokens[0],
368 deposit.amounts[0],
369 deposit.deposits[0],
370 _params
371 );
372 } else {
373 payload = abi.encodePacked(
374 bytes1(0x02),
375 _depositNonce,
376 deposit.hTokens[0],
377 deposit.tokens[0],
378 deposit.amounts[0],
379 deposit.deposits[0],
380 _params
381 );
382: }
While integers with a large number of bits are unlikely to overflow on human time scales, it is not strictly correct to use an unchecked
block around them, because eventually they will overflow, and unchecked
blocks are meant for cases where it's mathematically impossible for an operation to trigger an overflow (e.g. a prior require()
statement prevents the overflow case)
There are 15 instances of this issue:
see instances
File: src/BaseBranchRouter.sol
196: ++i;
GitHub: 196
File: src/BranchBridgeAgent.sol
451: ++i;
564: ++i;
File: src/BranchPort.sol
271: ++i;
309: i++;
File: src/MulticallRootRouter.sol
282: ++i;
371: ++i;
459: ++i;
561: ++i;
File: src/RootBridgeAgent.sol
338: ++i;
413: ++i;
1084: ++i;
File: src/RootBridgeAgentExecutor.sol
333: ++i;
GitHub: 333
File: src/VirtualAccount.sol
79: ++i;
106: ++i;
The longer a string of operations is, the harder it is to understand it. Consider splitting the full calculation into more steps, with more descriptive temporary variable names, and add extensive comments.
There are 8 instances of this issue:
File: src/BranchBridgeAgent.sol
518 _hTokens[i] = address(
519 uint160(
520 bytes20(
521 bytes32(
522 _sParams[
523 PARAMS_TKN_START + (PARAMS_ENTRY_SIZE * i) + ADDRESS_END_OFFSET:
524 PARAMS_TKN_START + (PARAMS_ENTRY_SIZE * currentIterationOffset)
525 ]
526 )
527 )
528 )
529: );
531 _tokens[i] = address(
532 uint160(
533 bytes20(
534 bytes32(
535 _sParams[
536 PARAMS_TKN_START + PARAMS_ENTRY_SIZE * (i + numOfAssets) + ADDRESS_END_OFFSET:
537 PARAMS_TKN_START + PARAMS_ENTRY_SIZE * (currentIterationOffset + numOfAssets)
538 ]
539 )
540 )
541 )
542: );
544 _amounts[i] = uint256(
545 bytes32(
546 _sParams[
547 PARAMS_TKN_START + PARAMS_AMT_OFFSET * numOfAssets + PARAMS_ENTRY_SIZE * i:
548 PARAMS_TKN_START + PARAMS_AMT_OFFSET * numOfAssets + PARAMS_ENTRY_SIZE * currentIterationOffset
549 ]
550 )
551: );
553 _deposits[i] = uint256(
554 bytes32(
555 _sParams[
556 PARAMS_TKN_START + PARAMS_DEPOSIT_OFFSET * numOfAssets + PARAMS_ENTRY_SIZE * i:
557 PARAMS_TKN_START + PARAMS_DEPOSIT_OFFSET * numOfAssets
558 + PARAMS_ENTRY_SIZE * currentIterationOffset
559 ]
560 )
561: );
File: src/RootBridgeAgentExecutor.sol
286 hTokens[i] = address(
287 uint160(
288 bytes20(
289 bytes32(
290 _dParams[
291 PARAMS_TKN_START + (PARAMS_ENTRY_SIZE * i) + ADDRESS_END_OFFSET:
292 PARAMS_TKN_START + (PARAMS_ENTRY_SIZE * currentIterationOffset)
293 ]
294 )
295 )
296 )
297: );
299 tokens[i] = address(
300 uint160(
301 bytes20(
302 bytes32(
303 _dParams[
304 PARAMS_TKN_START + PARAMS_ENTRY_SIZE * (i + numOfAssets) + ADDRESS_END_OFFSET:
305 PARAMS_TKN_START + PARAMS_ENTRY_SIZE * (currentIterationOffset + numOfAssets)
306 ]
307 )
308 )
309 )
310: );
312 amounts[i] = uint256(
313 bytes32(
314 _dParams[
315 PARAMS_TKN_START + PARAMS_AMT_OFFSET * numOfAssets + (PARAMS_ENTRY_SIZE * i):
316 PARAMS_TKN_START + PARAMS_AMT_OFFSET * numOfAssets
317 + (PARAMS_ENTRY_SIZE * currentIterationOffset)
318 ]
319 )
320: );
322 deposits[i] = uint256(
323 bytes32(
324 _dParams[
325 PARAMS_TKN_START + PARAMS_DEPOSIT_OFFSET * numOfAssets + (PARAMS_ENTRY_SIZE * i):
326 PARAMS_TKN_START + PARAMS_DEPOSIT_OFFSET * numOfAssets
327 + PARAMS_ENTRY_SIZE * currentIterationOffset
328 ]
329 )
330: );
The contract
s should expose an interface
so that other projects can more easily integrate with it, without having to develop their own non-standard variants.
There are 47 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
69: function depositToPort(address underlyingAddress, uint256 amount) external payable lock {
79: function withdrawFromPort(address localAddress, uint256 amount) external payable lock {
File: src/BaseBranchRouter.sol
60: function initialize(address _localBridgeAgentAddress) external onlyOwner {
GitHub: 60
File: src/BranchBridgeAgent.sol
149: receive() external payable {}
161 function getFeeEstimate(uint256 _gasLimit, uint256 _remoteBranchExecutionGas, bytes calldata _payload)
162 external
163 view
164 returns (uint256 _fee)
165: {
File: src/BranchBridgeAgentExecutor.sol
53: function executeNoSettlement(address _router, bytes calldata _payload) external payable onlyOwner {
66 function executeWithSettlement(address _recipient, address _router, bytes calldata _payload)
67 external
68 payable
69 onlyOwner
70: {
104 function executeWithSettlementMultiple(address _recipient, address _router, bytes calldata _payload)
105 external
106 payable
107 onlyOwner
108: {
File: src/BranchPort.sol
122: function initialize(address _coreBranchRouter, address _bridgeAgentFactory) external virtual onlyOwner {
GitHub: 122
File: src/CoreBranchRouter.sol
43 function addGlobalToken(address _globalAddress, uint256 _dstChainId, GasParams[3] calldata _gParams)
44 external
45 payable
46: {
62: function addLocalToken(address _underlyingAddress, GasParams calldata _gParams) external payable virtual {
File: src/CoreRootRouter.sol
83: function initialize(address _bridgeAgentAddress, address _hTokenFactory) external onlyOwner {
103 function addBranchToBridgeAgent(
104 address _rootBridgeAgent,
105 address _branchBridgeAgentFactory,
106 address _newBranchRouter,
107 address _refundee,
108 uint16 _dstChainId,
109 GasParams[2] calldata _gParams
110: ) external payable {
156 function toggleBranchBridgeAgentFactory(
157 address _rootBridgeAgentFactory,
158 address _branchBridgeAgentFactory,
159 address _refundee,
160 uint16 _dstChainId,
161 GasParams calldata _gParams
162: ) external payable onlyOwner {
186 function removeBranchBridgeAgent(
187 address _branchBridgeAgent,
188 address _refundee,
189 uint16 _dstChainId,
190 GasParams calldata _gParams
191: ) external payable onlyOwner {
212 function manageStrategyToken(
213 address _underlyingToken,
214 uint256 _minimumReservesRatio,
215 address _refundee,
216 uint16 _dstChainId,
217 GasParams calldata _gParams
218: ) external payable onlyOwner {
241 function managePortStrategy(
242 address _portStrategy,
243 address _underlyingToken,
244 uint256 _dailyManagementLimit,
245 bool _isUpdateDailyLimit,
246 address _refundee,
247 uint16 _dstChainId,
248 GasParams calldata _gParams
249: ) external payable onlyOwner {
270 function setCoreBranch(
271 address _refundee,
272 address _coreBranchRouter,
273 address _coreBranchBridgeAgent,
274 uint16 _dstChainId,
275 GasParams calldata _gParams
276: ) external payable {
GitHub: 83, 103, 156, 186, 212, 241, 270
File: src/MulticallRootRouter.sol
109: function initialize(address _bridgeAgentAddress) external onlyOwner {
209: function executeDepositMultiple(bytes calldata, DepositMultipleParams calldata, uint16) external payable {
File: src/RootBridgeAgent.sol
128: receive() external payable {}
140 function getFeeEstimate(
141 uint256 _gasLimit,
142 uint256 _remoteBranchExecutionGas,
143 bytes calldata _payload,
144 uint16 _dstChainId
145: ) external view returns (uint256 _fee) {
274: function retrieveSettlement(uint32 _settlementNonce, GasParams calldata _gParams) external payable lock {
423: function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64, bytes calldata _payload) public {
File: src/RootBridgeAgentExecutor.sol
50 function executeSystemRequest(address _router, bytes calldata _payload, uint16 _srcChainId)
51 external
52 payable
53 onlyOwner
54: {
66 function executeNoDeposit(address _router, bytes calldata _payload, uint16 _srcChainId)
67 external
68 payable
69 onlyOwner
70: {
82 function executeWithDeposit(address _router, bytes calldata _payload, uint16 _srcChainId)
83 external
84 payable
85 onlyOwner
86: {
115 function executeWithDepositMultiple(address _router, bytes calldata _payload, uint16 _srcChainId)
116 external
117 payable
118 onlyOwner
119: {
150 function executeSignedNoDeposit(address _account, address _router, bytes calldata _payload, uint16 _srcChainId)
151 external
152 payable
153 onlyOwner
154: {
167 function executeSignedWithDeposit(address _account, address _router, bytes calldata _payload, uint16 _srcChainId)
168 external
169 payable
170 onlyOwner
171: {
201 function executeSignedWithDepositMultiple(
202 address _account,
203 address _router,
204 bytes calldata _payload,
205 uint16 _srcChainId
206: ) external payable onlyOwner {
GitHub: 50, 66, 82, 115, 150, 167, 201
File: src/RootPort.sol
129: function initialize(address _bridgeAgentFactory, address _coreRootRouter) external onlyOwner {
147 function initializeCore(
148 address _coreRootBridgeAgent,
149 address _coreLocalBranchBridgeAgent,
150 address _localBranchPortAddress
151: ) external onlyOwner {
221 function isLocalToken(address _localAddress, uint256 _srcChainId, uint256 _dstChainId)
222 external
223 view
224 returns (bool)
225: {
File: src/VirtualAccount.sol
44: receive() external payable {}
85: function payableCall(PayableCall[] calldata calls) public payable returns (bytes[] memory returnData) {
File: src/factories/BranchBridgeAgentFactory.sol
87: function initialize(address _coreRootBridgeAgent) external virtual onlyOwner {
115 function createBridgeAgent(
116 address _newBranchRouterAddress,
117 address _rootBridgeAgentAddress,
118 address _rootBridgeAgentFactoryAddress
119: ) external virtual returns (address newBridgeAgent) {
File: src/factories/ERC20hTokenBranchFactory.sol
60: function initialize(address _wrappedNativeTokenAddress, address _coreRouter) external onlyOwner {
87: function getHTokens() external view returns (ERC20hTokenBranch[] memory) {
96 function createToken(string memory _name, string memory _symbol, uint8 _decimals, bool _addPrefix)
97 external
98 requiresCoreRouter
99 returns (ERC20hTokenBranch newToken)
100: {
File: src/factories/ERC20hTokenRootFactory.sol
49: function initialize(address _coreRouter) external onlyOwner {
63: function getHTokens() external view returns (ERC20hTokenRoot[] memory) {
76 function createToken(string memory _name, string memory _symbol, uint8 _decimals)
77 external
78 requiresCoreRouterOrPort
79 returns (ERC20hTokenRoot newToken)
80: {
File: src/factories/RootBridgeAgentFactory.sol
48: function createBridgeAgent(address _newRootRouterAddress) external returns (address newBridgeAgent) {
GitHub: 48
File: src/token/ERC20hTokenRoot.sol
57: function mint(address to, uint256 amount, uint256 chainId) external onlyOwner returns (bool) {
69: function burn(address from, uint256 amount, uint256 chainId) external onlyOwner {
One level of nesting can be removed by not having an else
block when the if
-block returns, and if (foo) { return 1; } else { return 2; }
becomes if (foo) { return 1; } return 2;
. A following else if
can become if
There are 2 instances of this issue:
File: src/BranchBridgeAgent.sol
671 if (executionState[nonce] == STATUS_DONE) {
672 revert AlreadyExecutedTransaction();
673 } else {
674 //Set settlement to retrieve mode, if not already set.
675 if (executionState[nonce] == STATUS_READY) executionState[nonce] = STATUS_RETRIEVE;
676 //Trigger fallback/Retry failed fallback
677 _performFallbackCall(recipient, nonce);
678: }
GitHub: 671
File: src/RootBridgeAgent.sol
704 if (executionState[_srcChainId][nonce] == STATUS_DONE) {
705 revert AlreadyExecutedTransaction();
706 } else {
707 //Set settlement to retrieve mode, if not already set.
708 if (executionState[_srcChainId][nonce] == STATUS_READY) {
709 executionState[_srcChainId][nonce] = STATUS_RETRIEVE;
710 }
711 //Trigger fallback/Retry failed fallback
712 _performFallbackCall(
713 payable(address(uint160(bytes20(_payload[PARAMS_START:PARAMS_START_SIGNED])))), nonce, _srcChainId
714 );
715: }
GitHub: 704
Events help non-contract tools to track changes, and timelocks prevent users from being surprised by changes
There is one instance of this issue:
File: src/BranchPort.sol
331 function setCoreRouter(address _newCoreRouter) external override requiresCoreRouter {
332 require(coreBranchRouterAddress != address(0), "CoreRouter address is zero");
333 require(_newCoreRouter != address(0), "New CoreRouter address is zero");
334 coreBranchRouterAddress = _newCoreRouter;
335: }
GitHub: 331
This especially problematic when the setter also emits the same value, which may be confusing to offline parsers
There are 11 instances of this issue:
File: src/BranchPort.sol
331 function setCoreRouter(address _newCoreRouter) external override requiresCoreRouter {
332 require(coreBranchRouterAddress != address(0), "CoreRouter address is zero");
333 require(_newCoreRouter != address(0), "New CoreRouter address is zero");
334 coreBranchRouterAddress = _newCoreRouter;
335: }
362 function addStrategyToken(address _token, uint256 _minimumReservesRatio) external override requiresCoreRouter {
363 if (_minimumReservesRatio >= DIVISIONER || _minimumReservesRatio < MIN_RESERVE_RATIO) {
364 revert InvalidMinimumReservesRatio();
365 }
366
367 strategyTokens.push(_token);
368 getMinimumTokenReserveRatio[_token] = _minimumReservesRatio;
369 isStrategyToken[_token] = true;
370
371 emit StrategyTokenAdded(_token, _minimumReservesRatio);
372: }
382 function addPortStrategy(address _portStrategy, address _token, uint256 _dailyManagementLimit)
383 external
384 override
385 requiresCoreRouter
386 {
387 if (!isStrategyToken[_token]) revert UnrecognizedStrategyToken();
388 portStrategies.push(_portStrategy);
389 strategyDailyLimitAmount[_portStrategy][_token] = _dailyManagementLimit;
390 isPortStrategy[_portStrategy][_token] = true;
391
392 emit PortStrategyAdded(_portStrategy, _token, _dailyManagementLimit);
393: }
403 function updatePortStrategy(address _portStrategy, address _token, uint256 _dailyManagementLimit)
404 external
405 override
406 requiresCoreRouter
407 {
408 strategyDailyLimitAmount[_portStrategy][_token] = _dailyManagementLimit;
409
410 emit PortStrategyUpdated(_portStrategy, _token, _dailyManagementLimit);
411: }
414 function setCoreBranchRouter(address _coreBranchRouter, address _coreBranchBridgeAgent)
415 external
416 override
417 requiresCoreRouter
418 {
419 coreBranchRouterAddress = _coreBranchRouter;
420 isBridgeAgent[_coreBranchBridgeAgent] = true;
421 bridgeAgents.push(_coreBranchBridgeAgent);
422
423 emit CoreBranchSet(_coreBranchRouter, _coreBranchBridgeAgent);
424: }
GitHub: 331, 362, 382, 403, 414
File: src/RootPort.sol
239 function setAddresses(
240 address _globalAddress,
241 address _localAddress,
242 address _underlyingAddress,
243 uint256 _srcChainId
244 ) external override requiresCoreRootRouter {
245 if (_globalAddress == address(0)) revert InvalidGlobalAddress();
246 if (_localAddress == address(0)) revert InvalidLocalAddress();
247 if (_underlyingAddress == address(0)) revert InvalidUnderlyingAddress();
248
249 isGlobalAddress[_globalAddress] = true;
250 getGlobalTokenFromLocal[_localAddress][_srcChainId] = _globalAddress;
251 getLocalTokenFromGlobal[_globalAddress][_srcChainId] = _localAddress;
252 getLocalTokenFromUnderlying[_underlyingAddress][_srcChainId] = _localAddress;
253 getUnderlyingTokenFromLocal[_localAddress][_srcChainId] = _underlyingAddress;
254
255 emit LocalTokenAdded(_underlyingAddress, _localAddress, _globalAddress, _srcChainId);
256: }
259 function setLocalAddress(address _globalAddress, address _localAddress, uint256 _srcChainId)
260 external
261 override
262 requiresCoreRootRouter
263 {
264 if (_localAddress == address(0)) revert InvalidLocalAddress();
265
266 getGlobalTokenFromLocal[_localAddress][_srcChainId] = _globalAddress;
267 getLocalTokenFromGlobal[_globalAddress][_srcChainId] = _localAddress;
268
269 emit GlobalTokenAdded(_localAddress, _globalAddress, _srcChainId);
270: }
382 function addBridgeAgent(address _manager, address _bridgeAgent) external override requiresBridgeAgentFactory {
383 if (isBridgeAgent[_bridgeAgent]) revert AlreadyAddedBridgeAgent();
384
385 bridgeAgents.push(_bridgeAgent);
386 getBridgeAgentManager[_bridgeAgent] = _manager;
387 isBridgeAgent[_bridgeAgent] = true;
388
389 emit BridgeAgentAdded(_bridgeAgent, _manager);
390: }
438 function addNewChain(
439 address _coreBranchBridgeAgentAddress,
440 uint256 _chainId,
441 string memory _wrappedGasTokenName,
442 string memory _wrappedGasTokenSymbol,
443 uint8 _wrappedGasTokenDecimals,
444 address _newLocalBranchWrappedNativeTokenAddress,
445 address _newUnderlyingBranchWrappedNativeTokenAddress
446 ) external override onlyOwner {
447 // Check if chain already added
448 if (isChainId[_chainId]) revert AlreadyAddedChain();
449
450 // Create new global token for new chain's wrapped native token
451 address newGlobalToken = address(
452 IERC20hTokenRootFactory(ICoreRootRouter(coreRootRouterAddress).hTokenFactoryAddress()).createToken(
453 _wrappedGasTokenName, _wrappedGasTokenSymbol, _wrappedGasTokenDecimals
454 )
455 );
456
457 // Sync new branch bridge agent with root core bridge agent
458 IBridgeAgent(ICoreRootRouter(coreRootRouterAddress).bridgeAgentAddress()).syncBranchBridgeAgent(
459 _coreBranchBridgeAgentAddress, _chainId
460 );
461
462 // Update State
463
464 // 1. Add new chain to chainId mapping
465 isChainId[_chainId] = true;
466 // 2. Add new chain to global address mapping
467 isGlobalAddress[newGlobalToken] = true;
468 // 3. Add new branch local token to global token address mapping
469 getGlobalTokenFromLocal[_newLocalBranchWrappedNativeTokenAddress][_chainId] = newGlobalToken;
470 // 4. Add new global token to branch local token address mapping
471 getLocalTokenFromGlobal[newGlobalToken][_chainId] = _newLocalBranchWrappedNativeTokenAddress;
472 // 5. Add new branch underlying token to branch local token address mapping
473 getLocalTokenFromUnderlying[_newUnderlyingBranchWrappedNativeTokenAddress][_chainId] =
474 _newLocalBranchWrappedNativeTokenAddress;
475 // 6. Add new branch local token to branch underlying token address mapping
476 getUnderlyingTokenFromLocal[_newLocalBranchWrappedNativeTokenAddress][_chainId] =
477 _newUnderlyingBranchWrappedNativeTokenAddress;
478
479 emit NewChainAdded(_chainId);
480: }
483 function addEcosystemToken(address _ecoTokenGlobalAddress) external override onlyOwner {
484 // Check if token already added
485 if (isGlobalAddress[_ecoTokenGlobalAddress]) revert AlreadyAddedEcosystemToken();
486
487 // Check if token is already a underlying token in current chain
488 if (getUnderlyingTokenFromLocal[_ecoTokenGlobalAddress][localChainId] != address(0)) {
489 revert AlreadyAddedEcosystemToken();
490 }
491
492 // Check if token is already a local branch token in current chain
493 if (getLocalTokenFromUnderlying[_ecoTokenGlobalAddress][localChainId] != address(0)) {
494 revert AlreadyAddedEcosystemToken();
495 }
496
497 // Update State
498 // 1. Add new global token to global address mapping
499 isGlobalAddress[_ecoTokenGlobalAddress] = true;
500 // 2. Add new branch local token address to global token mapping
501 getGlobalTokenFromLocal[_ecoTokenGlobalAddress][localChainId] = _ecoTokenGlobalAddress;
502 // 3. Add new global token to branch local token address mapping
503 getLocalTokenFromGlobal[_ecoTokenGlobalAddress][localChainId] = _ecoTokenGlobalAddress;
504
505 emit EcosystemTokenAdded(_ecoTokenGlobalAddress);
506: }
509 function setCoreRootRouter(address _coreRootRouter, address _coreRootBridgeAgent) external override onlyOwner {
510 if (_coreRootRouter == address(0)) revert InvalidCoreRootRouter();
511 if (_coreRootBridgeAgent == address(0)) revert InvalidCoreRootBridgeAgent();
512
513 coreRootRouterAddress = _coreRootRouter;
514 coreRootBridgeAgentAddress = _coreRootBridgeAgent;
515 getBridgeAgentManager[_coreRootBridgeAgent] = owner();
516
517 emit CoreRootSet(_coreRootRouter, _coreRootBridgeAgent);
518: }
GitHub: 239, 259, 382, 438, 483, 509
The instances below point to one of two functions with the same name. Consider naming each function differently, in order to make code navigation and analysis easier.
There are 6 instances of this issue:
File: src/BranchBridgeAgent.sol
730 function _execute(bool _hasFallbackToggled, uint32 _settlementNonce, address _refundee, bytes memory _calldata)
731 private
732: {
GitHub: 730
File: src/BranchPort.sol
188: function replenishReserves(address _strategy, address _token) external override lock {
GitHub: 188
File: src/RootBridgeAgent.sol
768 function _execute(
769 bool _hasFallbackToggled,
770 uint32 _depositNonce,
771 address _refundee,
772 bytes memory _calldata,
773 uint16 _srcChainId
774: ) private {
GitHub: 768
File: src/RootPort.sol
221 function isLocalToken(address _localAddress, uint256 _srcChainId, uint256 _dstChainId)
222 external
223 view
224 returns (bool)
225: {
GitHub: 221
File: src/interfaces/IBranchPort.sol
72: function replenishReserves(address _strategy, address _token) external;
GitHub: 72
File: src/interfaces/IRootPort.sol
144 function isLocalToken(address _localAddress, uint256 _srcChainId, uint256 _dstChainId)
145 external
146 view
147: returns (bool);
GitHub: 144
The contract's interface should be imported first, followed by each of the interfaces it uses, followed by all other files. The examples below do not follow this layout.
There are 4 instances of this issue:
File: src/BranchBridgeAgent.sol
9 import {
10 Deposit,
11 DepositInput,
12 DepositMultipleInput,
13 GasParams,
14 IBranchBridgeAgent,
15 ILayerZeroReceiver,
16 SettlementMultipleParams
17: } from "./interfaces/IBranchBridgeAgent.sol";
GitHub: 9
File: src/BranchBridgeAgentExecutor.sol
12: import {SettlementParams, SettlementMultipleParams} from "./interfaces/IBranchBridgeAgent.sol";
GitHub: 12
File: src/RootBridgeAgent.sol
14 import {
15 GasParams,
16 DepositParams,
17 DepositMultipleParams,
18 ILayerZeroReceiver,
19 IRootBridgeAgent,
20 Settlement,
21 SettlementInput,
22 SettlementMultipleInput
23: } from "./interfaces/IRootBridgeAgent.sol";
GitHub: 14
File: src/VirtualAccount.sol
10: import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
GitHub: 10
When deploying contracts, you should use the latest released version of Solidity. Apart from exceptional cases, only the latest version receives security fixes.
https://docs.soliditylang.org/en/v0.8.20/
Since deployed contracts should not use floating pragmas, I've flagged all instances where a version prior to 0.8.19 is allowed by the version pragma
There are 23 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/ArbitrumBranchPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/ArbitrumCoreBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BaseBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BranchBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BranchBridgeAgentExecutor.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BranchPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/CoreBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/CoreRootRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/MulticallRootRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/MulticallRootRouterLibZip.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/RootBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/RootBridgeAgentExecutor.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/RootPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/VirtualAccount.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/BranchBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/ERC20hTokenBranchFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/ERC20hTokenRootFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/RootBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/BridgeAgentConstants.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/token/ERC20hTokenBranch.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/token/ERC20hTokenRoot.sol
2: pragma solidity ^0.8.0;
GitHub: 2
There are 7 instances of this issue:
File: src/CoreRootRouter.sol
112 if (msg.sender != IPort(rootPortAddress).getBridgeAgentManager(_rootBridgeAgent)) {
113 revert UnauthorizedCallerNotManager();
114: }
278: require(msg.sender == rootPortAddress, "Only root port can call");
File: src/RootBridgeAgent.sol
248 if (msg.sender != address(IPort(localPortAddress).getUserAccount(settlementReference.owner))) {
249 revert NotSettlementOwner();
250: }
286 if (msg.sender != address(IPort(localPortAddress).getUserAccount(settlementOwner))) {
287 revert NotSettlementOwner();
288: }
312 if (msg.sender != address(IPort(localPortAddress).getUserAccount(settlementOwner))) {
313 revert NotSettlementOwner();
314: }
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
84 require(
85 msg.sender == localCoreBranchRouterAddress, "Only the Core Branch Router can create a new Bridge Agent."
86: );
GitHub: 84
File: src/factories/BranchBridgeAgentFactory.sol
120 require(
121 msg.sender == localCoreBranchRouterAddress, "Only the Core Branch Router can create a new Bridge Agent."
122: );
GitHub: 120
Note that some file names may indicate an interface, but actually contain abstract contracts
There are 23 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/ArbitrumBranchPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/ArbitrumCoreBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BaseBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BranchBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BranchBridgeAgentExecutor.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BranchPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/CoreBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/CoreRootRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/MulticallRootRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/MulticallRootRouterLibZip.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/RootBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/RootBridgeAgentExecutor.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/RootPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/VirtualAccount.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/BranchBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/ERC20hTokenBranchFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/ERC20hTokenRootFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/RootBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/BridgeAgentConstants.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/token/ERC20hTokenBranch.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/token/ERC20hTokenRoot.sol
2: pragma solidity ^0.8.0;
GitHub: 2
Adding a way to quickly halt protocol functionality in an emergency, rather than having to pause individual contracts one-by-one, will make in-progress hack mitigation faster and much less stressful.
There are 13 instances of this issue:
see instances
File: src/BaseBranchRouter.sol
25: contract BaseBranchRouter is IBranchRouter, Ownable {
GitHub: 25
File: src/BranchBridgeAgentExecutor.sol
29: contract BranchBridgeAgentExecutor is Ownable, BridgeAgentConstants {
GitHub: 29
File: src/BranchPort.sol
17: contract BranchPort is Ownable, IBranchPort {
GitHub: 17
File: src/CoreRootRouter.sol
38 contract CoreRootRouter is IRootRouter, Ownable {
39 /*///////////////////////////////////////////////////////////////
40 CORE ROOT ROUTER STATE
41 //////////////////////////////////////////////////////////////*/
42
43: /// @notice Boolean to indicate if the contract is in set up mode.
GitHub: 38
File: src/MulticallRootRouter.sol
57: contract MulticallRootRouter is IRootRouter, Ownable {
GitHub: 57
File: src/RootBridgeAgentExecutor.sol
27 contract RootBridgeAgentExecutor is Ownable, BridgeAgentConstants {
28 /*///////////////////////////////////////////////////////////////
29 CONSTRUCTOR
30 //////////////////////////////////////////////////////////////*/
31 /**
32 * @notice Constructor for Root Bridge Agent Executor.
33 * @param _rootBridgeAgent the owner of the contract in charge of calling the different execution functions.
34: */
GitHub: 27
File: src/RootPort.sol
16: contract RootPort is Ownable, IRootPort {
GitHub: 16
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
17 contract ArbitrumBranchBridgeAgentFactory is BranchBridgeAgentFactory {
18 /*///////////////////////////////////////////////////////////////
19 CONSTRUCTOR
20 //////////////////////////////////////////////////////////////*/
21
22 /**
23 * @notice Constructor for Bridge Agent Factory Contract.
24 * @param _rootChainId Root Chain Layer Zero Id.
25 * @param _rootBridgeAgentFactoryAddress Root Bridge Agent Factory Address.
26 * @param _localCoreBranchRouterAddress Local Core Branch Router Address.
27 * @param _localPortAddress Local Branch Port Address.
28 * @param _owner Owner of the contract.
29: */
GitHub: 17
File: src/factories/BranchBridgeAgentFactory.sol
19 contract BranchBridgeAgentFactory is Ownable, IBranchBridgeAgentFactory {
20: /// @notice Local Chain Id.
GitHub: 19
File: src/factories/ERC20hTokenBranchFactory.sol
12 contract ERC20hTokenBranchFactory is Ownable, IERC20hTokenBranchFactory {
13: /// @notice Local Network Identifier.
GitHub: 12
File: src/factories/ERC20hTokenRootFactory.sol
12 contract ERC20hTokenRootFactory is Ownable, IERC20hTokenRootFactory {
13: /// @notice Local Network Identifier.
GitHub: 12
File: src/token/ERC20hTokenBranch.sol
12: contract ERC20hTokenBranch is ERC20, Ownable, IERC20hTokenBranch {
GitHub: 12
File: src/token/ERC20hTokenRoot.sol
12 contract ERC20hTokenRoot is ERC20, Ownable, IERC20hTokenRoot {
13: /// @inheritdoc IERC20hTokenRoot
GitHub: 12
There are 46 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
/// @audit Missing '@return '
11 function deploy(uint16 _localChainId, address _daoAddress, address _localRouterAddress, address _localPortAddress)
12 external
13: returns (ArbitrumBranchBridgeAgent)
GitHub: 11
File: src/BranchBridgeAgent.sol
/// @audit Missing '@return '
24 function deploy(
25 uint16 _rootChainId,
26 uint16 _localChainId,
27 address _rootBridgeAgentAddress,
28 address _lzEndpointAddress,
29 address _localRouterAddress,
30 address _localPortAddress
31: ) external returns (BranchBridgeAgent) {
GitHub: 24
File: src/BranchBridgeAgentExecutor.sol
/// @audit Missing '@return '
16: function deploy() external returns (address) {
GitHub: 16
File: src/MulticallRootRouter.sol
/// @audit Missing '@return blockNumber'
/// @audit Missing '@return returnData'
483 /**
484 * @notice Function to perform a set of actions on the omnichain environment without using the user's Virtual Acccount.
485 * @param calls to be executed.
486 *
487 */
488 function _multicall(IMulticall.Call[] memory calls)
489 internal
490: returns (uint256 blockNumber, bytes[] memory returnData)
/// @audit Missing '@return '
581: function _decode(bytes calldata data) internal pure virtual returns (bytes memory) {
File: src/MulticallRootRouterLibZip.sol
/// @audit Missing '@return '
37: function _decode(bytes calldata data) internal pure override returns (bytes memory) {
GitHub: 37
File: src/RootBridgeAgent.sol
/// @audit Missing '@return _payload'
966 function _createSettlement(
967 uint32 _settlementNonce,
968 address payable _refundee,
969 address _recipient,
970 uint16 _dstChainId,
971 bytes memory _params,
972 address _globalAddress,
973 uint256 _amount,
974 uint256 _deposit,
975 bool _hasFallbackToggled
976: ) internal returns (bytes memory _payload) {
/// @audit Missing '@return _payload'
1045 function _createSettlementMultiple(
1046 uint32 _settlementNonce,
1047 address payable _refundee,
1048 address _recipient,
1049 uint16 _dstChainId,
1050 address[] memory _globalAddresses,
1051 uint256[] memory _amounts,
1052 uint256[] memory _deposits,
1053 bytes memory _params,
1054 bool _hasFallbackToggled
1055: ) internal returns (bytes memory _payload) {
File: src/RootBridgeAgentExecutor.sol
/// @audit Missing '@return '
14: function deploy(address _rootBridgeAgent) external returns (address) {
/// @audit Missing '@return dParams'
260 * 4. N * 32 bytes for the amount of underlying tokens to be bridged in.
261 * 5. Each of the 4 token related arrays are of length N and start at the following indexes:
262 * 1. PARAMS_TKN_START [hToken address has no offset from token information start].
263 * 2. PARAMS_TKN_START + (PARAMS_ADDRESS_SIZE * N)
264 * 3. PARAMS_TKN_START + (PARAMS_AMT_OFFSET * N)
265 * 4. PARAMS_TKN_START + (PARAMS_DEPOSIT_OFFSET * N)
266 *
267 */
268 function _bridgeInMultiple(address _recipient, bytes calldata _dParams, uint16 _srcChainId)
269 internal
270: returns (DepositMultipleParams memory dParams)
File: src/RootPort.sol
/// @audit Missing '@return '
184 /**
185 * @notice View Function returns Local Token's Local Address on another chain.
186 * @param _localAddress The address of the token in the local chain.
187 * @param _srcChainId The chainId of the chain where the token is deployed.
188 * @param _dstChainId The chainId of the chain for which the token address is requested.
189 */
190 function _getLocalToken(address _localAddress, uint256 _srcChainId, uint256 _dstChainId)
191 internal
192 view
193: returns (address)
/// @audit Missing '@return newAccount'
355 /**
356 * @notice Creates a new virtual account for a user.
357 * @param _user address of the user to associate a virtual account with.
358 */
359: function addVirtualAccount(address _user) internal returns (VirtualAccount newAccount) {
File: src/VirtualAccount.sol
/// @audit Missing '@return '
147: function isContract(address addr) internal view returns (bool) {
GitHub: 147
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
/// @audit Missing '@return newBridgeAgent'
74 /**
75 * @notice Creates a new bridge agent for a branch chain.
76 * @param _newBranchRouterAddress Address of the new branch router.
77 * @param _rootBridgeAgentAddress Address of the root bridge agent to connect to.
78 */
79 function createBridgeAgent(
80 address _newBranchRouterAddress,
81 address _rootBridgeAgentAddress,
82 address _rootBridgeAgentFactoryAddress
83: ) external virtual override returns (address newBridgeAgent) {
GitHub: 74
File: src/factories/BranchBridgeAgentFactory.sol
/// @audit Missing '@return newBridgeAgent'
110 /**
111 * @notice Creates a new bridge agent for a new branch chain.
112 * @param _newBranchRouterAddress Address of the new branch router.
113 * @param _rootBridgeAgentAddress Address of the root bridge agent to connect to.
114 */
115 function createBridgeAgent(
116 address _newBranchRouterAddress,
117 address _rootBridgeAgentAddress,
118 address _rootBridgeAgentFactoryAddress
119: ) external virtual returns (address newBridgeAgent) {
GitHub: 110
File: src/factories/ERC20hTokenRootFactory.sol
/// @audit Missing '@return newToken'
70 /**
71 * @notice Function to create a new hToken.
72 * @param _name Name of the Token.
73 * @param _symbol Symbol of the Token.
74 * @param _decimals Decimals of the Token.
75 */
76 function createToken(string memory _name, string memory _symbol, uint8 _decimals)
77 external
78 requiresCoreRouterOrPort
79: returns (ERC20hTokenRoot newToken)
GitHub: 70
File: src/interfaces/IBranchBridgeAgent.sol
/// @audit Missing '@return '
104 /**
105 * @notice External function that returns a given deposit entry.
106 * @param depositNonce Identifier for user deposit.
107 *
108 */
109: function getDepositEntry(uint32 depositNonce) external view returns (Deposit memory);
/// @audit Missing '@return '
307 /**
308 * @notice Function to request balance clearance from a Port to a given address.
309 * @param sParams encode packed multiple settlement info.
310 *
311 */
312 function clearTokens(bytes calldata sParams, address recipient)
313 external
314: returns (SettlementMultipleParams memory);
File: src/interfaces/IBranchRouter.sol
/// @audit Missing '@return '
26 /// @notice External function to return the Branch Chain's Local Port Address.
27: function localPortAddress() external view returns (address);
/// @audit Missing '@return '
29 /// @notice Address for local Branch Bridge Agent who processes requests and interacts with local port.
30: function localBridgeAgentAddress() external view returns (address);
/// @audit Missing '@return '
32 /// @notice Local Bridge Agent Executor Address.
33: function bridgeAgentExecutorAddress() external view returns (address);
/// @audit Missing '@return '
74 /**
75 * @notice External function that returns a given deposit entry.
76 * @param depositNonce Identifier for user deposit.
77 *
78 */
79: function getDepositEntry(uint32 depositNonce) external view returns (Deposit memory);
File: src/interfaces/IERC20hTokenBranchFactory.sol
/// @audit Missing '@return newToken'
17 /**
18 * @notice Function to create a new Branch hToken.
19 * @param _name Name of the Token.
20 * @param _symbol Symbol of the Token.
21 * @param _decimals Decimals of the Token.
22 * @param _addPrefix Boolean to add or not the chain prefix to the token name and symbol.
23 */
24 function createToken(string memory _name, string memory _symbol, uint8 _decimals, bool _addPrefix)
25 external
26: returns (ERC20hTokenBranch newToken);
GitHub: 17
File: src/interfaces/IERC20hTokenRootFactory.sol
/// @audit Missing '@return newToken'
18 /**
19 * @notice Function to create a new hToken.
20 * @param _name Name of the Token.
21 * @param _symbol Symbol of the Token.
22 * @param _decimals Decimals of the Token.
23 */
24 function createToken(string memory _name, string memory _symbol, uint8 _decimals)
25 external
26: returns (ERC20hTokenRoot newToken);
GitHub: 18
File: src/interfaces/ILayerZeroEndpoint.sol
/// @audit Missing '@return '
43: function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);
/// @audit Missing '@return '
47: function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);
/// @audit Missing '@return nativeFee'
/// @audit Missing '@return zroFee'
55 function estimateFees(
56 uint16 _dstChainId,
57 address _userApplication,
58 bytes calldata _payload,
59 bool _payInZRO,
60 bytes calldata _adapterParam
61: ) external view returns (uint256 nativeFee, uint256 zroFee);
/// @audit Missing '@return '
64: function getChainId() external view returns (uint16);
/// @audit Missing '@return '
75: function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);
/// @audit Missing '@return '
79: function getSendLibraryAddress(address _userApplication) external view returns (address);
/// @audit Missing '@return '
83: function getReceiveLibraryAddress(address _userApplication) external view returns (address);
/// @audit Missing '@return '
87: function isSendingPayload() external view returns (bool);
/// @audit Missing '@return '
91: function isReceivingPayload() external view returns (bool);
/// @audit Missing '@return '
98 function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint256 _configType)
99 external
100 view
101: returns (bytes memory);
/// @audit Missing '@return '
105: function getSendVersion(address _userApplication) external view returns (uint16);
/// @audit Missing '@return '
109: function getReceiveVersion(address _userApplication) external view returns (uint16);
GitHub: 43, 47, 55, 55, 64, 75, 79, 83, 87, 91, 98, 105, 109
File: src/interfaces/IMulticall2.sol
/// @audit Missing '@return blockNumber'
/// @audit Missing '@return returnData'
20: function aggregate(Call[] memory calls) external returns (uint256 blockNumber, bytes[] memory returnData);
File: src/interfaces/IRootBridgeAgent.sol
/// @audit Missing '@return '
106 /**
107 * @notice External function that returns a given settlement entry.
108 * @param _settlementNonce Identifier for token settlement.
109 *
110 */
111: function getSettlementEntry(uint32 _settlementNonce) external view returns (Settlement memory);
GitHub: 106
File: src/interfaces/IRootBridgeAgentFactory.sol
/// @audit Missing '@return newBridgeAgent'
16: function createBridgeAgent(address newRootRouterAddress) external returns (address newBridgeAgent);
GitHub: 16
File: src/interfaces/IRootPort.sol
/// @audit Missing '@return '
11: function bridgeAgentAddress() external view returns (address);
/// @audit Missing '@return '
12: function hTokenFactoryAddress() external view returns (address);
/// @audit Missing '@return account'
257 /**
258 * @notice Gets the virtual account given a user address.
259 * @param _user address of the user to get the virtual account for.
260 */
261: function fetchVirtualAccount(address _user) external returns (VirtualAccount account);
File: src/token/ERC20hTokenRoot.sol
/// @audit Missing '@return '
51 /**
52 * @notice Mints new tokens and updates the total supply for the given chain.
53 * @param to Address to mint tokens to.
54 * @param amount Amount of tokens to mint.
55 * @param chainId Chain Id of the chain to mint tokens to.
56 */
57: function mint(address to, uint256 amount, uint256 chainId) external onlyOwner returns (bool) {
GitHub: 51
There are 111 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
/// @audit Missing '@param _localChainId'
/// @audit Missing '@param _daoAddress'
/// @audit Missing '@param _localRouterAddress'
/// @audit Missing '@param _localPortAddress'
11: function deploy(uint16 _localChainId, address _daoAddress, address _localRouterAddress, address _localPortAddress)
/// @audit Missing '@param _endpoint'
123 /// @notice Verifies the caller is the Root Bridge Agent.
124 /// @dev Internal function used in modifier to reduce contract bytesize.
125: function _requiresEndpoint(address _endpoint, bytes calldata) internal view override {
File: src/BranchBridgeAgent.sol
/// @audit Missing '@param _rootChainId'
24 function deploy(
25: uint16 _rootChainId,
/// @audit Missing '@param _localChainId'
24 function deploy(
25 uint16 _rootChainId,
26: uint16 _localChainId,
/// @audit Missing '@param _rootBridgeAgentAddress'
24 function deploy(
25 uint16 _rootChainId,
26 uint16 _localChainId,
27: address _rootBridgeAgentAddress,
/// @audit Missing '@param _lzEndpointAddress'
24 function deploy(
25 uint16 _rootChainId,
26 uint16 _localChainId,
27 address _rootBridgeAgentAddress,
28: address _lzEndpointAddress,
/// @audit Missing '@param _localRouterAddress'
24 function deploy(
25 uint16 _rootChainId,
26 uint16 _localChainId,
27 address _rootBridgeAgentAddress,
28 address _lzEndpointAddress,
29: address _localRouterAddress,
/// @audit Missing '@param _localPortAddress'
24 function deploy(
25 uint16 _rootChainId,
26 uint16 _localChainId,
27 address _rootBridgeAgentAddress,
28 address _lzEndpointAddress,
29 address _localRouterAddress,
30: address _localPortAddress
/// @audit Missing '@param _endpoint'
/// @audit Missing '@param _srcAddress'
935 /// @notice Internal function for caller verification. To be overwritten in `ArbitrumBranchBridgeAgent'.
936: function _requiresEndpoint(address _endpoint, bytes calldata _srcAddress) internal view virtual {
GitHub: 24, 24, 24, 24, 24, 24, 935, 935
File: src/BranchPort.sol
/// @audit Missing '@param _strategyTokenDebt'
430 /**
431 * @notice Returns amount of Strategy Tokens
432 * @param _token Address of a given Strategy Token.
433 * @return uint256 excess reserves
434 */
435: function _excessReserves(uint256 _strategyTokenDebt, address _token) internal view returns (uint256) {
/// @audit Missing '@param _strategyTokenDebt'
/// @audit Missing '@param currBalance'
444 /**
445 * @notice Returns amount of Strategy Tokens needed to reach minimum reserves
446 * @param _token Address of a given Strategy Token.
447 * @return uint256 excess reserves
448 */
449: function _reservesLacking(uint256 _strategyTokenDebt, address _token, uint256 currBalance)
File: src/CoreBranchRouter.sol
/// @audit Missing '@param _decimals'
160 * @param _symbol token symbol.
161 * @param _refundee the address of the excess gas receiver.
162 * @param _gParams Gas parameters for remote execution.
163 * @dev FUNC ID: 1
164 * @dev all hTokens have 18 decimals.
165 */
166 function _receiveAddGlobalToken(
167 address _globalAddress,
168 string memory _name,
169 string memory _symbol,
170: uint8 _decimals,
GitHub: 160
File: src/CoreRootRouter.sol
/// @audit Missing '@param _bridgeAgentAddress'
/// @audit Missing '@param _hTokenFactory'
83: function initialize(address _bridgeAgentAddress, address _hTokenFactory) external onlyOwner {
/// @audit Missing '@param _rootBridgeAgent'
95 /**
96 * @notice Add a new Chain (Branch Bridge Agent and respective Router) to a Root Bridge Agent.
97 * @param _branchBridgeAgentFactory Address of the branch Bridge Agent Factory.
98 * @param _newBranchRouter Address of the new branch router.
99 * @param _refundee Address of the excess gas receiver.
100 * @param _dstChainId Chain Id of the branch chain where the new Bridge Agent will be deployed.
101 * @param _gParams Gas parameters for remote execution.
102 */
103 function addBranchToBridgeAgent(
104: address _rootBridgeAgent,
File: src/MulticallRootRouter.sol
/// @audit Missing '@param gasParams'
505 * @param depositOut Amount of output hTokens to deposit.
506 * @param dstChainId Chain Id of the destination chain.
507 */
508 function _approveAndCallOut(
509 address refundee,
510 address recipient,
511 address outputToken,
512 uint256 amountOut,
513 uint256 depositOut,
514 uint16 dstChainId,
515: GasParams memory gasParams
/// @audit Missing '@param dstChainId'
540 * @param amountsOut Total amount of tokens to send.
541 * @param depositsOut Amounts of tokens to withdraw from the destination port.
542 *
543 */
544 function _approveMultipleAndCallOut(
545 address refundee,
546 address recipient,
547 address[] memory outputTokens,
548 uint256[] memory amountsOut,
549 uint256[] memory depositsOut,
550: uint16 dstChainId,
/// @audit Missing '@param gasParams'
541 * @param depositsOut Amounts of tokens to withdraw from the destination port.
542 *
543 */
544 function _approveMultipleAndCallOut(
545 address refundee,
546 address recipient,
547 address[] memory outputTokens,
548 uint256[] memory amountsOut,
549 uint256[] memory depositsOut,
550 uint16 dstChainId,
551: GasParams memory gasParams
/// @audit Missing '@param data'
581: function _decode(bytes calldata data) internal pure virtual returns (bytes memory) {
File: src/MulticallRootRouterLibZip.sol
/// @audit Missing '@param _localChainId'
/// @audit Missing '@param _localPortAddress'
/// @audit Missing '@param _multicallAddress'
29: constructor(uint256 _localChainId, address _localPortAddress, address _multicallAddress)
/// @audit Missing '@param data'
37: function _decode(bytes calldata data) internal pure override returns (bytes memory) {
File: src/RootBridgeAgent.sol
/// @audit Missing '@param _value'
858 address[] memory _hTokens,
859 address[] memory _tokens,
860 uint256[] memory _amounts,
861 uint256[] memory _deposits,
862 bytes memory _params,
863 uint32 _settlementNonce,
864 address payable _refundee,
865 address _recipient,
866 uint16 _dstChainId,
867 GasParams memory _gParams,
868: uint256 _value
/// @audit Missing '@param _refundee'
933 /**
934 * @notice Internal function performs call to Layerzero Enpoint Contract for cross-chain messaging.
935 * @param _depositNonce branch deposit nonce.
936 * @param _dstChainId Chain ID of destination chain.
937 */
938: function _performFallbackCall(address payable _refundee, uint32 _depositNonce, uint16 _dstChainId) internal {
File: src/RootBridgeAgentExecutor.sol
/// @audit Missing '@param _rootBridgeAgent'
14: function deploy(address _rootBridgeAgent) external returns (address) {
/// @audit Missing '@param _recipient'
237 /**
238 * @notice Internal function to move assets from branch chain to root omnichain environment.
239 * @param _dParams Cross-Chain Deposit of Multiple Tokens Params.
240 * @param _srcChainId chain to bridge from.
241 *
242 */
243: function _bridgeIn(address _recipient, DepositParams memory _dParams, uint16 _srcChainId) internal {
/// @audit Missing '@param _recipient'
258 * 2. N * 32 bytes for the underlying token address.
259 * 3. N * 32 bytes for the amount of hTokens to be bridged in.
260 * 4. N * 32 bytes for the amount of underlying tokens to be bridged in.
261 * 5. Each of the 4 token related arrays are of length N and start at the following indexes:
262 * 1. PARAMS_TKN_START [hToken address has no offset from token information start].
263 * 2. PARAMS_TKN_START + (PARAMS_ADDRESS_SIZE * N)
264 * 3. PARAMS_TKN_START + (PARAMS_AMT_OFFSET * N)
265 * 4. PARAMS_TKN_START + (PARAMS_DEPOSIT_OFFSET * N)
266 *
267 */
268: function _bridgeInMultiple(address _recipient, bytes calldata _dParams, uint16 _srcChainId)
File: src/RootPort.sol
/// @audit Missing '@param _to'
/// @audit Missing '@param _hToken'
/// @audit Missing '@param _amount'
304: function bridgeToLocalBranchFromRoot(address _to, address _hToken, uint256 _amount)
File: src/VirtualAccount.sol
/// @audit Missing '@param addr'
147: function isContract(address addr) internal view returns (bool) {
GitHub: 147
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
/// @audit Missing '@param _rootBridgeAgentFactoryAddress'
74 /**
75 * @notice Creates a new bridge agent for a branch chain.
76 * @param _newBranchRouterAddress Address of the new branch router.
77 * @param _rootBridgeAgentAddress Address of the root bridge agent to connect to.
78 */
79 function createBridgeAgent(
80 address _newBranchRouterAddress,
81 address _rootBridgeAgentAddress,
82: address _rootBridgeAgentFactoryAddress
GitHub: 74
File: src/factories/BranchBridgeAgentFactory.sol
/// @audit Missing '@param _rootBridgeAgentFactoryAddress'
110 /**
111 * @notice Creates a new bridge agent for a new branch chain.
112 * @param _newBranchRouterAddress Address of the new branch router.
113 * @param _rootBridgeAgentAddress Address of the root bridge agent to connect to.
114 */
115 function createBridgeAgent(
116 address _newBranchRouterAddress,
117 address _rootBridgeAgentAddress,
118: address _rootBridgeAgentFactoryAddress
GitHub: 110
File: src/interfaces/IBranchBridgeAgent.sol
/// @audit Missing '@param recipient'
307 /**
308 * @notice Function to request balance clearance from a Port to a given address.
309 * @param sParams encode packed multiple settlement info.
310 *
311 */
312: function clearTokens(bytes calldata sParams, address recipient)
GitHub: 307
File: src/interfaces/IBranchPort.sol
/// @audit Missing '@param _underlyingAddresses'
96 /**
97 * @notice Setter function to increase local hToken supply.
98 * @param _recipient hToken receiver.
99 * @param _localAddresses token addresses.
100 * @param _amounts amount of tokens.
101 *
102 */
103 function bridgeInMultiple(
104 address _recipient,
105 address[] memory _localAddresses,
106: address[] memory _underlyingAddresses,
/// @audit Missing '@param _deposits'
98 * @param _recipient hToken receiver.
99 * @param _localAddresses token addresses.
100 * @param _amounts amount of tokens.
101 *
102 */
103 function bridgeInMultiple(
104 address _recipient,
105 address[] memory _localAddresses,
106 address[] memory _underlyingAddresses,
107 uint256[] memory _amounts,
108: uint256[] memory _deposits
/// @audit Missing '@param _depositor'
111 /**
112 * @notice Setter function to decrease local hToken supply.
113 * @param _localAddress token address.
114 * @param _amount amount of tokens.
115 * @param _deposit amount of underlying tokens.
116 *
117 */
118 function bridgeOut(
119: address _depositor,
/// @audit Missing '@param _underlyingAddress'
111 /**
112 * @notice Setter function to decrease local hToken supply.
113 * @param _localAddress token address.
114 * @param _amount amount of tokens.
115 * @param _deposit amount of underlying tokens.
116 *
117 */
118 function bridgeOut(
119 address _depositor,
120 address _localAddress,
121: address _underlyingAddress,
/// @audit Missing '@param _minimumReservesRatio'
177 /**
178 * @notice Adds a new strategy token.
179 * @param _token address of the token to add to the Strategy Tokens
180 */
181: function addStrategyToken(address _token, uint256 _minimumReservesRatio) external;
/// @audit Missing '@param _token'
/// @audit Missing '@param _dailyManagementLimit'
189 /**
190 * @notice Adds a new Port strategy to the given port
191 * @param _portStrategy address of the bridge agent factory to add to the Port
192 */
193: function addPortStrategy(address _portStrategy, address _token, uint256 _dailyManagementLimit) external;
/// @audit Missing '@param _token'
195 /**
196 * @notice Reverts the toggle on the given port strategy. If it's active, it will de-activate it and vice-versa.
197 * @param _portStrategy address of the bridge agent factory to add to the Port
198 */
199: function togglePortStrategy(address _portStrategy, address _token) external;
GitHub: 96, 98, 111, 111, 177, 189, 189, 195
File: src/interfaces/ILayerZeroEndpoint.sol
/// @audit Missing '@param _dstChainId'
15 function send(
16: uint16 _dstChainId,
/// @audit Missing '@param _destination'
15 function send(
16 uint16 _dstChainId,
17: bytes calldata _destination,
/// @audit Missing '@param _payload'
15 function send(
16 uint16 _dstChainId,
17 bytes calldata _destination,
18: bytes calldata _payload,
/// @audit Missing '@param _refundAddress'
15 function send(
16 uint16 _dstChainId,
17 bytes calldata _destination,
18 bytes calldata _payload,
19: address payable _refundAddress,
/// @audit Missing '@param _zroPaymentAddress'
15 function send(
16 uint16 _dstChainId,
17 bytes calldata _destination,
18 bytes calldata _payload,
19 address payable _refundAddress,
20: address _zroPaymentAddress,
/// @audit Missing '@param _adapterParams'
15 function send(
16 uint16 _dstChainId,
17 bytes calldata _destination,
18 bytes calldata _payload,
19 address payable _refundAddress,
20 address _zroPaymentAddress,
21: bytes calldata _adapterParams
/// @audit Missing '@param _srcChainId'
31 function receivePayload(
32: uint16 _srcChainId,
/// @audit Missing '@param _srcAddress'
31 function receivePayload(
32 uint16 _srcChainId,
33: bytes calldata _srcAddress,
/// @audit Missing '@param _dstAddress'
31 function receivePayload(
32 uint16 _srcChainId,
33 bytes calldata _srcAddress,
34: address _dstAddress,
/// @audit Missing '@param _nonce'
31 function receivePayload(
32 uint16 _srcChainId,
33 bytes calldata _srcAddress,
34 address _dstAddress,
35: uint64 _nonce,
/// @audit Missing '@param _gasLimit'
31 function receivePayload(
32 uint16 _srcChainId,
33 bytes calldata _srcAddress,
34 address _dstAddress,
35 uint64 _nonce,
36: uint256 _gasLimit,
/// @audit Missing '@param _payload'
31 function receivePayload(
32 uint16 _srcChainId,
33 bytes calldata _srcAddress,
34 address _dstAddress,
35 uint64 _nonce,
36 uint256 _gasLimit,
37: bytes calldata _payload
/// @audit Missing '@param _srcChainId'
/// @audit Missing '@param _srcAddress'
43: function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);
/// @audit Missing '@param _dstChainId'
/// @audit Missing '@param _srcAddress'
47: function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);
/// @audit Missing '@param _dstChainId'
55 function estimateFees(
56: uint16 _dstChainId,
/// @audit Missing '@param _userApplication'
55 function estimateFees(
56 uint16 _dstChainId,
57: address _userApplication,
/// @audit Missing '@param _payload'
55 function estimateFees(
56 uint16 _dstChainId,
57 address _userApplication,
58: bytes calldata _payload,
/// @audit Missing '@param _payInZRO'
55 function estimateFees(
56 uint16 _dstChainId,
57 address _userApplication,
58 bytes calldata _payload,
59: bool _payInZRO,
/// @audit Missing '@param _adapterParam'
55 function estimateFees(
56 uint16 _dstChainId,
57 address _userApplication,
58 bytes calldata _payload,
59 bool _payInZRO,
60: bytes calldata _adapterParam
/// @audit Missing '@param _srcChainId'
/// @audit Missing '@param _srcAddress'
/// @audit Missing '@param _payload'
70: function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;
/// @audit Missing '@param _srcChainId'
/// @audit Missing '@param _srcAddress'
75: function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);
/// @audit Missing '@param _userApplication'
79: function getSendLibraryAddress(address _userApplication) external view returns (address);
/// @audit Missing '@param _userApplication'
83: function getReceiveLibraryAddress(address _userApplication) external view returns (address);
/// @audit Missing '@param _version'
/// @audit Missing '@param _chainId'
/// @audit Missing '@param _userApplication'
/// @audit Missing '@param _configType'
98: function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint256 _configType)
/// @audit Missing '@param _userApplication'
105: function getSendVersion(address _userApplication) external view returns (uint16);
/// @audit Missing '@param _userApplication'
109: function getReceiveVersion(address _userApplication) external view returns (uint16);
GitHub: 15, 15, 15, 15, 15, 15, 31, 31, 31, 31, 31, 31, 43, 43, 47, 47, 55, 55, 55, 55, 55, 70, 70, 70, 75, 75, 79, 83, 98, 98, 98, 98, 105, 109
File: src/interfaces/ILayerZeroReceiver.sol
/// @audit Missing '@param _srcChainId'
/// @audit Missing '@param _srcAddress'
/// @audit Missing '@param _nonce'
/// @audit Missing '@param _payload'
11: function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
/// @audit Missing '@param _version'
/// @audit Missing '@param _chainId'
/// @audit Missing '@param _configType'
/// @audit Missing '@param _config'
11: function setConfig(uint16 _version, uint16 _chainId, uint256 _configType, bytes calldata _config) external;
/// @audit Missing '@param _version'
15: function setSendVersion(uint16 _version) external;
/// @audit Missing '@param _version'
19: function setReceiveVersion(uint16 _version) external;
/// @audit Missing '@param _srcChainId'
/// @audit Missing '@param _srcAddress'
24: function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;
GitHub: 11, 11, 11, 11, 15, 19, 24, 24
File: src/interfaces/IMulticall2.sol
/// @audit Missing '@param calls'
20: function aggregate(Call[] memory calls) external returns (uint256 blockNumber, bytes[] memory returnData);
GitHub: 20
File: src/interfaces/IRootBridgeAgent.sol
/// @audit Missing '@param _refundee'
160 /**
161 * @notice External function performs call to LayerZero Endpoint Contract for cross-chain messaging.
162 * @param _recipient address to receive any outstanding gas on the destination chain.
163 * @param _dstChainId Chain to bridge to.
164 * @param _params Calldata for function call.
165 * @param _gParams Gas Parameters for cross-chain message.
166 * @dev Internal function performs call to LayerZero Endpoint Contract for cross-chain messaging.
167 */
168 function callOut(
169: address payable _refundee,
GitHub: 160
File: src/interfaces/IRootBridgeAgentFactory.sol
/// @audit Missing '@param newRootRouterAddress'
16: function createBridgeAgent(address newRootRouterAddress) external returns (address newBridgeAgent);
GitHub: 16
File: src/interfaces/IRootPort.sol
/// @audit Missing '@param _refundee'
13 function setCoreBranch(
14: address _refundee,
/// @audit Missing '@param _coreBranchRouter'
13 function setCoreBranch(
14 address _refundee,
15: address _coreBranchRouter,
/// @audit Missing '@param _coreBranchBridgeAgent'
13 function setCoreBranch(
14 address _refundee,
15 address _coreBranchRouter,
16: address _coreBranchBridgeAgent,
/// @audit Missing '@param _dstChainId'
13 function setCoreBranch(
14 address _refundee,
15 address _coreBranchRouter,
16 address _coreBranchBridgeAgent,
17: uint16 _dstChainId,
/// @audit Missing '@param _gParams'
13 function setCoreBranch(
14 address _refundee,
15 address _coreBranchRouter,
16 address _coreBranchBridgeAgent,
17 uint16 _dstChainId,
18: GasParams calldata _gParams
/// @audit Missing '@param _underlyingAddress'
232 /**
233 * @notice Setter function to update a Global hToken's Local hToken Address.
234 * @param _globalAddress new hToken address to update.
235 * @param _localAddress new underlying/native token address to set.
236 *
237 */
238 function setAddresses(
239 address _globalAddress,
240 address _localAddress,
241: address _underlyingAddress,
/// @audit Missing '@param _srcChainId'
232 /**
233 * @notice Setter function to update a Global hToken's Local hToken Address.
234 * @param _globalAddress new hToken address to update.
235 * @param _localAddress new underlying/native token address to set.
236 *
237 */
238 function setAddresses(
239 address _globalAddress,
240 address _localAddress,
241 address _underlyingAddress,
242: uint256 _srcChainId
/// @audit Missing '@param _srcChainId'
245 /**
246 * @notice Setter function to update a Global hToken's Local hToken Address.
247 * @param _globalAddress new hToken address to update.
248 * @param _localAddress new underlying/native token address to set.
249 *
250 */
251: function setLocalAddress(address _globalAddress, address _localAddress, uint256 _srcChainId) external;
GitHub: 13, 13, 13, 13, 13, 232, 232, 245
File: src/token/ERC20hTokenBranch.sol
/// @audit Missing '@param chainName'
13 constructor(
14: string memory chainName,
/// @audit Missing '@param chainSymbol'
13 constructor(
14 string memory chainName,
15: string memory chainSymbol,
/// @audit Missing '@param _name'
13 constructor(
14 string memory chainName,
15 string memory chainSymbol,
16: string memory _name,
/// @audit Missing '@param _symbol'
13 constructor(
14 string memory chainName,
15 string memory chainSymbol,
16 string memory _name,
17: string memory _symbol,
/// @audit Missing '@param _decimals'
13 constructor(
14 string memory chainName,
15 string memory chainSymbol,
16 string memory _name,
17 string memory _symbol,
18: uint8 _decimals,
/// @audit Missing '@param _owner'
13 constructor(
14 string memory chainName,
15 string memory chainSymbol,
16 string memory _name,
17 string memory _symbol,
18 uint8 _decimals,
19: address _owner
The functions below take in an unbounded array, and make function calls for entries in the array. While the function will revert if it eventually runs out of gas, it may be a nicer user experience to require()
that the length of the array is below some reasonable maximum, so that the user doesn't have to use up a full transaction's gas only to see that the transaction reverts.
There are 7 instances of this issue:
File: src/BaseBranchRouter.sol
192 for (uint256 i = 0; i < _hTokens.length;) {
193 _transferAndApproveToken(_hTokens[i], _tokens[i], _amounts[i], _deposits[i]);
194
195 unchecked {
196 ++i;
197 }
198: }
GitHub: 192
File: src/BranchPort.sol
257 for (uint256 i = 0; i < length;) {
258 // Check if hTokens are being bridged in
259 if (_amounts[i] - _deposits[i] > 0) {
260 unchecked {
261 _bridgeIn(_recipient, _localAddresses[i], _amounts[i] - _deposits[i]);
262 }
263 }
264
265 // Check if underlying tokens are being cleared
266 if (_deposits[i] > 0) {
267 withdraw(_recipient, _underlyingAddresses[i], _deposits[i]);
268 }
269
270 unchecked {
271 ++i;
272 }
273: }
305 for (uint256 i = 0; i < length;) {
306 _bridgeOut(_depositor, _localAddresses[i], _underlyingAddresses[i], _amounts[i], _deposits[i]);
307
308 unchecked {
309 i++;
310 }
311: }
File: src/MulticallRootRouter.sol
557 for (uint256 i = 0; i < outputTokens.length;) {
558 // Approve Root Port to spend output hTokens.
559 outputTokens[i].safeApprove(_bridgeAgentAddress, amountsOut[i]);
560 unchecked {
561 ++i;
562 }
563: }
GitHub: 557
File: src/RootBridgeAgent.sol
1070 for (uint256 i = 0; i < hTokens.length;) {
1071 // Populate Addresses for Settlement
1072 hTokens[i] = IPort(localPortAddress).getLocalTokenFromGlobal(_globalAddresses[i], _dstChainId);
1073 tokens[i] = IPort(localPortAddress).getUnderlyingTokenFromLocal(hTokens[i], _dstChainId);
1074
1075 // Avoid stack too deep
1076 uint16 destChainId = _dstChainId;
1077
1078 // Update State to reflect bridgeOut
1079 _updateStateOnBridgeOut(
1080 msg.sender, _globalAddresses[i], hTokens[i], tokens[i], _amounts[i], _deposits[i], destChainId
1081 );
1082
1083 unchecked {
1084 ++i;
1085 }
1086: }
GitHub: 1070
File: src/VirtualAccount.sol
70 for (uint256 i = 0; i < length;) {
71 bool success;
72 Call calldata _call = calls[i];
73
74 if (isContract(_call.target)) (success, returnData[i]) = _call.target.call(_call.callData);
75
76 if (!success) revert CallFailed();
77
78 unchecked {
79 ++i;
80 }
81: }
90 for (uint256 i = 0; i < length;) {
91 _call = calls[i];
92 uint256 val = _call.value;
93 // Humanity will be a Type V Kardashev Civilization before this overflows - andreas
94 // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256
95 unchecked {
96 valAccumulator += val;
97 }
98
99 bool success;
100
101 if (isContract(_call.target)) (success, returnData[i]) = _call.target.call{value: val}(_call.callData);
102
103 if (!success) revert CallFailed();
104
105 unchecked {
106 ++i;
107 }
108: }
There is one instance of this issue:
File: src/interfaces/ILayerZeroEndpoint.sol
/// @audit ILayerZeroUserApplicationConfig
7: interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
GitHub: 7
Consider whether the number of casts is really necessary, or whether using a different type would be more appropriate. Alternatively, add comments to explain in detail why the casts are necessary, and any implicit reasons why the cast does not introduce an overflow.
There are 59 instances of this issue:
File: src/BranchBridgeAgent.sol
500 // Parse Tokens Length
501: uint8 numOfAssets = uint8(bytes1(_sParams[0]));
503 // Parse Nonce
504: uint32 nonce = uint32(bytes4(_sParams[PARAMS_START:PARAMS_TKN_START]));
517 // Parse Params
518 _hTokens[i] = address(
519 uint160(
520 bytes20(
521 bytes32(
522 _sParams[
523 PARAMS_TKN_START + (PARAMS_ENTRY_SIZE * i) + ADDRESS_END_OFFSET:
524 PARAMS_TKN_START + (PARAMS_ENTRY_SIZE * currentIterationOffset)
525 ]
526 )
527 )
528 )
529: );
530
531 _tokens[i] = address(
532 uint160(
533 bytes20(
534 bytes32(
535 _sParams[
536 PARAMS_TKN_START + PARAMS_ENTRY_SIZE * (i + numOfAssets) + ADDRESS_END_OFFSET:
537 PARAMS_TKN_START + PARAMS_ENTRY_SIZE * (currentIterationOffset + numOfAssets)
538 ]
539 )
540 )
541 )
542: );
543
544 _amounts[i] = uint256(
545 bytes32(
546 _sParams[
547 PARAMS_TKN_START + PARAMS_AMT_OFFSET * numOfAssets + PARAMS_ENTRY_SIZE * i:
548 PARAMS_TKN_START + PARAMS_AMT_OFFSET * numOfAssets + PARAMS_ENTRY_SIZE * currentIterationOffset
549 ]
550 )
551: );
552
553 _deposits[i] = uint256(
554 bytes32(
555 _sParams[
556 PARAMS_TKN_START + PARAMS_DEPOSIT_OFFSET * numOfAssets + PARAMS_ENTRY_SIZE * i:
557 PARAMS_TKN_START + PARAMS_DEPOSIT_OFFSET * numOfAssets
558 + PARAMS_ENTRY_SIZE * currentIterationOffset
559 ]
560 )
561: );
682 //Get nonce
683: nonce = uint32(bytes4(_payload[PARAMS_START:PARAMS_TKN_START]));
664 // Parse recipient
665: address payable recipient = payable(address(uint160(bytes20(_payload[PARAMS_START:PARAMS_START_SIGNED]))));
667 //Get nonce
668: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));
639 // Parse recipient
640: address payable recipient = payable(address(uint160(bytes20(_payload[PARAMS_START:PARAMS_START_SIGNED]))));
642 // Parse deposit nonce
643: nonce = uint32(bytes4(_payload[22:26]));
617 // Parse recipient
618: address payable recipient = payable(address(uint160(bytes20(_payload[PARAMS_START:PARAMS_START_SIGNED]))));
620 // Parse Settlement Nonce
621: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));
600 // Get Settlement Nonce
601: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));
942 if (_srcAddress.length != 40) revert LayerZeroUnauthorizedCaller();
943: if (rootBridgeAgentAddress != address(uint160(bytes20(_srcAddress[20:])))) revert LayerZeroUnauthorizedCaller();
GitHub: 500, 503, 517, 530, 543, 552, 682, 664, 667, 639, 642, 617, 620, 600, 942
File: src/BranchBridgeAgentExecutor.sol
72 SettlementParams memory sParams = SettlementParams({
73: settlementNonce: uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED])),
74 recipient: _recipient,
75: hToken: address(uint160(bytes20(_payload[PARAMS_TKN_START_SIGNED:45]))),
75 hToken: address(uint160(bytes20(_payload[PARAMS_TKN_START_SIGNED:45]))),
76: token: address(uint160(bytes20(_payload[45:65]))),
76 token: address(uint160(bytes20(_payload[45:65]))),
77: amount: uint256(bytes32(_payload[65:97])),
77 amount: uint256(bytes32(_payload[65:97])),
78: deposit: uint256(bytes32(_payload[97:PARAMS_SETTLEMENT_OFFSET]))
109 // Parse Values
110: uint256 assetsOffset = uint8(bytes1(_payload[PARAMS_START_SIGNED])) * PARAMS_TKN_SET_SIZE_MULTIPLE;
GitHub: 72, 74, 75, 76, 77, 109
File: src/RootBridgeAgent.sol
719 // Parse nonce
720: nonce = uint32(bytes4(_payload[PARAMS_START:PARAMS_TKN_START]));
700 //Parse deposit nonce
701: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));
712 _performFallbackCall(
713: payable(address(uint160(bytes20(_payload[PARAMS_START:PARAMS_START_SIGNED])))), nonce, _srcChainId
618 // Parse deposit nonce
619: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED + PARAMS_START:PARAMS_START_SIGNED + PARAMS_TKN_START]));
627 VirtualAccount userAccount = IPort(localPortAddress).fetchVirtualAccount(
628: address(uint160(bytes20(_payload[PARAMS_START:PARAMS_START_SIGNED])))
641 nonce,
642: address(uint160(bytes20(_payload[PARAMS_START:PARAMS_START_SIGNED]))),
578 // Parse deposit nonce
579: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));
587 VirtualAccount userAccount = IPort(localPortAddress).fetchVirtualAccount(
588: address(uint160(bytes20(_payload[PARAMS_START:PARAMS_START_SIGNED])))
601 nonce,
602: address(uint160(bytes20(_payload[PARAMS_START:PARAMS_START_SIGNED]))),
540 // Parse deposit nonce
541: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));
549 VirtualAccount userAccount = IPort(localPortAddress).fetchVirtualAccount(
550: address(uint160(bytes20(_payload[PARAMS_START:PARAMS_START_SIGNED])))
514 // Parse deposit nonce
515: nonce = uint32(bytes4(_payload[2:6]));
491 //Parse Deposit Nonce
492: nonce = uint32(bytes4(_payload[PARAMS_START:PARAMS_TKN_START]));
468 // Parse Deposit Nonce
469: nonce = uint32(bytes4(_payload[PARAMS_START:PARAMS_TKN_START]));
445 // Parse deposit nonce
446: nonce = uint32(bytes4(_payload[PARAMS_START:PARAMS_TKN_START]));
1211
1212: if (getBranchBridgeAgent[_srcChain] != address(uint160(bytes20(_srcAddress[PARAMS_ADDRESS_SIZE:])))) {
GitHub: 719, 700, 712, 618, 627, 641, 578, 587, 601, 540, 549, 514, 491, 468, 445, 1211
File: src/RootBridgeAgentExecutor.sol
88 DepositParams memory dParams = DepositParams({
89: depositNonce: uint32(bytes4(_payload[PARAMS_START:PARAMS_TKN_START])),
89 depositNonce: uint32(bytes4(_payload[PARAMS_START:PARAMS_TKN_START])),
90: hToken: address(uint160(bytes20(_payload[PARAMS_TKN_START:PARAMS_TKN_START_SIGNED]))),
90 hToken: address(uint160(bytes20(_payload[PARAMS_TKN_START:PARAMS_TKN_START_SIGNED]))),
91: token: address(uint160(bytes20(_payload[PARAMS_TKN_START_SIGNED:45]))),
91 token: address(uint160(bytes20(_payload[PARAMS_TKN_START_SIGNED:45]))),
92: amount: uint256(bytes32(_payload[45:77])),
92 amount: uint256(bytes32(_payload[45:77])),
93: deposit: uint256(bytes32(_payload[77:PARAMS_TKN_SET_SIZE]))
124 PARAMS_START:
125: PARAMS_END_OFFSET + uint256(uint8(bytes1(_payload[PARAMS_START]))) * PARAMS_TKN_SET_SIZE_MULTIPLE
129
130: uint256 numOfAssets = uint8(bytes1(_payload[PARAMS_START]));
173 DepositParams memory dParams = DepositParams({
174: depositNonce: uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED])),
174 depositNonce: uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED])),
175: hToken: address(uint160(bytes20(_payload[PARAMS_TKN_START_SIGNED:45]))),
175 hToken: address(uint160(bytes20(_payload[PARAMS_TKN_START_SIGNED:45]))),
176: token: address(uint160(bytes20(_payload[45:65]))),
176 token: address(uint160(bytes20(_payload[45:65]))),
177: amount: uint256(bytes32(_payload[65:97])),
177 amount: uint256(bytes32(_payload[65:97])),
178: deposit: uint256(bytes32(_payload[97:PARAMS_SETTLEMENT_OFFSET]))
212 PARAMS_END_SIGNED_OFFSET
213: + uint256(uint8(bytes1(_payload[PARAMS_START_SIGNED]))) * PARAMS_TKN_SET_SIZE_MULTIPLE
221 > PARAMS_END_SIGNED_OFFSET
222: + uint256(uint8(bytes1(_payload[PARAMS_START_SIGNED]))) * PARAMS_TKN_SET_SIZE_MULTIPLE
227 PARAMS_END_SIGNED_OFFSET
228: + uint256(uint8(bytes1(_payload[PARAMS_START_SIGNED]))) * PARAMS_TKN_SET_SIZE_MULTIPLE:
272 // Parse Parameters
273: uint8 numOfAssets = uint8(bytes1(_dParams[0]));
273 uint8 numOfAssets = uint8(bytes1(_dParams[0]));
274: uint32 nonce = uint32(bytes4(_dParams[PARAMS_START:5]));
285 // Parse Params
286 hTokens[i] = address(
287 uint160(
288 bytes20(
289 bytes32(
290 _dParams[
291 PARAMS_TKN_START + (PARAMS_ENTRY_SIZE * i) + ADDRESS_END_OFFSET:
292 PARAMS_TKN_START + (PARAMS_ENTRY_SIZE * currentIterationOffset)
293 ]
294 )
295 )
296 )
297: );
298
299 tokens[i] = address(
300 uint160(
301 bytes20(
302 bytes32(
303 _dParams[
304 PARAMS_TKN_START + PARAMS_ENTRY_SIZE * (i + numOfAssets) + ADDRESS_END_OFFSET:
305 PARAMS_TKN_START + PARAMS_ENTRY_SIZE * (currentIterationOffset + numOfAssets)
306 ]
307 )
308 )
309 )
310: );
311
312 amounts[i] = uint256(
313 bytes32(
314 _dParams[
315 PARAMS_TKN_START + PARAMS_AMT_OFFSET * numOfAssets + (PARAMS_ENTRY_SIZE * i):
316 PARAMS_TKN_START + PARAMS_AMT_OFFSET * numOfAssets
317 + (PARAMS_ENTRY_SIZE * currentIterationOffset)
318 ]
319 )
320: );
321
322 deposits[i] = uint256(
323 bytes32(
324 _dParams[
325 PARAMS_TKN_START + PARAMS_DEPOSIT_OFFSET * numOfAssets + (PARAMS_ENTRY_SIZE * i):
326 PARAMS_TKN_START + PARAMS_DEPOSIT_OFFSET * numOfAssets
327 + PARAMS_ENTRY_SIZE * currentIterationOffset
328 ]
329 )
330: );
280
281: for (uint256 i = 0; i < uint256(uint8(numOfAssets));) {
GitHub: 88, 89, 90, 91, 92, 124, 129, 173, 174, 175, 176, 177, 212, 221, 227, 272, 273, 285, 298, 311, 321, 280
Ensure that events follow the best practice of check-effects-interaction, and are emitted before external calls
There are 7 instances of this issue:
File: src/BranchPort.sol
/// @audit withdraw() prior to emission
184: emit DebtRepaid(msg.sender, _token, _amount);
/// @audit withdraw() prior to emission
218: emit DebtRepaid(_strategy, _token, amountToWithdraw);
File: src/RootBridgeAgent.sol
/// @audit fetchVirtualAccount() prior to emission
736: emit LogExecute(nonce, _srcChainId);
GitHub: 736
File: src/RootPort.sol
/// @audit syncBranchBridgeAgent() prior to emission
406: emit BridgeAgentSynced(_newBranchBridgeAgent, _rootBridgeAgent, _branchChainId);
/// @audit syncBranchBridgeAgent() prior to emission
479: emit NewChainAdded(_chainId);
/// @audit syncBranchBridgeAgent() prior to emission
535: emit CoreBranchSet(_coreBranchRouter, _coreBranchBridgeAgent, _dstChainId);
/// @audit syncBranchBridgeAgent() prior to emission
549: emit CoreBranchSynced(_coreBranchRouter, _coreBranchBridgeAgent, _dstChainId);
assembly{ id := chainid() }
=> uint256 id = block.chainid
, assembly { size := extcodesize() }
=> uint256 size = address().code.length
, assembly { hash := extcodehash() }
=> bytes32 hash = address().codehash
There are some automated tools that will flag a project as having higher complexity if there is inline-assembly, so it's best to avoid using it where it's not necessary
There is one instance of this issue:
File: src/VirtualAccount.sol
149 assembly {
150 size := extcodesize(addr)
151: }
GitHub: 149
Consider whether reasonable bounds checks for variables would be useful
There are 9 instances of this issue:
see instances
File: src/ArbitrumBranchPort.sol
41: localChainId = _localChainId;
GitHub: 41
File: src/CoreRootRouter.sol
72: rootChainId = _rootChainId;
GitHub: 72
File: src/MulticallRootRouter.sol
96: localChainId = _localChainId;
GitHub: 96
File: src/RootBridgeAgent.sol
116: localChainId = _localChainId;
GitHub: 116
File: src/RootPort.sol
112: localChainId = _localChainId;
GitHub: 112
File: src/factories/ERC20hTokenBranchFactory.sol
46: localChainId = _localChainId;
GitHub: 46
File: src/factories/ERC20hTokenRootFactory.sol
36: localChainId = _localChainId;
GitHub: 36
File: src/factories/RootBridgeAgentFactory.sol
34: rootChainId = _rootChainId;
GitHub: 34
File: src/token/ERC20hTokenRoot.sol
42: localChainId = _localChainId;
GitHub: 42
By using --via-ir
or {"viaIR": true}
, the compiler is able to use more advanced multi-function optimizations, for extra gas savings.
There is one instance of this issue:
File: Various Files
[G‑02] Multiple address
/ID mappings can be combined into a single mapping
of an address
/ID to a struct
, where appropriate
Saves a storage slot for the mapping. Depending on the circumstances and sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot. Finally, if both fields are accessed in the same function, can save ~42 gas per access due to not having to recalculate the key's keccak256 hash (Gkeccak256 - 30 gas) and that calculation's associated stack operations.
There are 5 instances of this issue:
File: src/BranchPort.sol
58 mapping(address token => uint256 debt) public getStrategyTokenDebt;
59
60 /// @notice Mapping returns the minimum ratio of a given Strategy Token the Port should hold.
61 mapping(address token => uint256 minimumReserveRatio) public getMinimumTokenReserveRatio;
62
63 /*///////////////////////////////////////////////////////////////
64 PORT STRATEGIES STATE
65 //////////////////////////////////////////////////////////////*/
66
67 /// @notice Mapping returns true if Port Strategy is allowed to manage a given Strategy Token.
68: mapping(address strategy => mapping(address token => bool isActiveStrategy)) public isPortStrategy;
74 mapping(address strategy => mapping(address token => uint256 debt)) public getPortStrategyTokenDebt;
75
76 /// @notice Mapping returns the last time a given Port Strategy managed a given Strategy Token.
77 mapping(address strategy => mapping(address token => uint256 lastManaged)) public lastManaged;
78
79 /// @notice Mapping returns the time limit a given Port Strategy must wait before managing a Strategy Token.
80 mapping(address strategy => mapping(address token => uint256 dailyLimitAmount)) public strategyDailyLimitAmount;
81
82 /// @notice Mapping returns the amount of a Strategy Token a given Port Strategy can manage.
83 mapping(address strategy => mapping(address token => uint256 dailyLimitRemaining)) public
84: strategyDailyLimitRemaining;
File: src/RootBridgeAgent.sol
62 mapping(uint256 chainId => address branchBridgeAgent) public getBranchBridgeAgent;
63
64 /// @notice Message Path for each connected Branch Bridge Agent as bytes for Layzer Zero interaction = localAddress + destinationAddress abi.encodePacked()
65 mapping(uint256 chainId => bytes branchBridgeAgentPath) public getBranchBridgeAgentPath;
66
67 /// @notice If true, bridge agent manager has allowed for a new given branch bridge agent to be synced/added.
68: mapping(uint256 chainId => bool allowed) public isBranchBridgeAgentAllowed;
GitHub: 62
File: src/RootPort.sol
70 mapping(address bridgeAgent => address bridgeAgentManager) public getBridgeAgentManager;
71
72 /*///////////////////////////////////////////////////////////////
73 BRIDGE AGENT FACTORIES
74 //////////////////////////////////////////////////////////////*/
75
76 /// @notice Mapping from Underlying Address to isUnderlying (bool).
77: mapping(address bridgeAgentFactory => bool isActive) public isBridgeAgentFactory;
87 mapping(address token => bool isGlobalToken) public isGlobalAddress;
88
89 /// @notice ChainId -> Local Address -> Global Address
90 mapping(address chainId => mapping(uint256 localAddress => address globalAddress)) public getGlobalTokenFromLocal;
91
92 /// @notice ChainId -> Global Address -> Local Address
93 mapping(address chainId => mapping(uint256 globalAddress => address localAddress)) public getLocalTokenFromGlobal;
94
95 /// @notice ChainId -> Underlying Address -> Local Address
96 mapping(address chainId => mapping(uint256 underlyingAddress => address localAddress)) public
97 getLocalTokenFromUnderlying;
98
99 /// @notice Mapping from Local Address to Underlying Address.
100 mapping(address chainId => mapping(uint256 localAddress => address underlyingAddress)) public
101: getUnderlyingTokenFromLocal;
Avoids a Gsset (20000 gas) in the constructor, and replaces the first access in each transaction (Gcoldsload - 2100 gas) and each access thereafter (Gwarmacces - 100 gas) with a PUSH32
(3 gas).
While string
s are not value types, and therefore cannot be immutable
/constant
if not hard-coded outside of the constructor, the same behavior can be achieved by making the current contract abstract
with virtual
functions for the string
accessors, and having a child contract override the functions with the hard-coded implementation-specific values.
There are 3 instances of this issue:
File: src/BranchBridgeAgent.sol
/// @audit rootBridgeAgentPath (constructor)
142: rootBridgeAgentPath = abi.encodePacked(_rootBridgeAgentAddress, address(this));
GitHub: 142
File: src/factories/ERC20hTokenBranchFactory.sol
/// @audit chainName (constructor)
44: chainName = string.concat(_chainName, " Ulysses");
/// @audit chainSymbol (constructor)
45: chainSymbol = string.concat(_chainSymbol, "-u");
Prior to 0.8.10 the compiler inserted extra code, including EXTCODESIZE
(100 gas), to check for contract existence for external function calls. In more recent solidity versions, the compiler will not insert these checks if the external call has a return value. Similar behavior can be achieved in earlier versions by using low-level calls, since low-level calls never check for contract existence
There are 52 instances of this issue:
see instances
File: src/ArbitrumBranchPort.sol
/// @audit getLocalTokenFromUnderlying()
60: address _globalToken = IRootPort(_rootPortAddress).getLocalTokenFromUnderlying(_underlyingAddress, localChainId);
/// @audit getUnderlyingTokenFromLocal()
87: IRootPort(_rootPortAddress).getUnderlyingTokenFromLocal(_globalAddress, localChainId);
File: src/ArbitrumCoreBranchRouter.sol
/// @audit name()
56: string.concat("Arbitrum Ulysses ", ERC20(_underlyingAddress).name()),
/// @audit symbol()
57: string.concat("arb-u", ERC20(_underlyingAddress).symbol()),
/// @audit decimals()
58: ERC20(_underlyingAddress).decimals()
/// @audit createBridgeAgent()
102: address newBridgeAgent = IBridgeAgentFactory(_branchBridgeAgentFactory).createBridgeAgent(
File: src/BaseBranchRouter.sol
/// @audit localPortAddress()
63: localPortAddress = IBridgeAgent(_localBridgeAgentAddress).localPortAddress();
/// @audit bridgeAgentExecutorAddress()
64: bridgeAgentExecutorAddress = IBridgeAgent(_localBridgeAgentAddress).bridgeAgentExecutorAddress();
File: src/BranchBridgeAgent.sol
/// @audit estimateFees()
166: (_fee,) = ILayerZeroEndpoint(lzEndpointAddress).estimateFees(
GitHub: 166
File: src/BranchBridgeAgentExecutor.sol
/// @audit clearTokens()
114: SettlementMultipleParams memory sParams = BranchBridgeAgent(payable(msg.sender)).clearTokens(
GitHub: 114
File: src/BranchPort.sol
/// @audit balanceOf()
175: uint256 currBalance = ERC20(_token).balanceOf(address(this));
/// @audit balanceOf()
181: require(ERC20(_token).balanceOf(address(this)) - currBalance == _amount, "Port Strategy Withdraw Failed");
/// @audit balanceOf()
193: uint256 currBalance = ERC20(_token).balanceOf(address(this));
/// @audit balanceOf()
214: ERC20(_token).balanceOf(address(this)) - currBalance == amountToWithdraw, "Port Strategy Withdraw Failed"
/// @audit balanceOf()
436: uint256 currBalance = ERC20(_token).balanceOf(address(this));
GitHub: 175, 181, 193, 214, 436
File: src/CoreBranchRouter.sol
/// @audit decimals()
64: uint8 decimals = ERC20(_underlyingAddress).decimals();
/// @audit createToken()
67: ERC20hToken newToken = ITokenFactory(hTokenFactoryAddress).createToken(
/// @audit name()
/// @audit symbol()
68: ERC20(_underlyingAddress).name(), ERC20(_underlyingAddress).symbol(), decimals, true
/// @audit createToken()
175: ERC20hToken newToken = ITokenFactory(hTokenFactoryAddress).createToken(_name, _symbol, _decimals, false);
/// @audit createBridgeAgent()
216: address newBridgeAgent = IBridgeAgentFactory(_branchBridgeAgentFactory).createBridgeAgent(
GitHub: 64, 67, 68, 68, 175, 216
File: src/CoreRootRouter.sol
/// @audit bridgeAgentExecutorAddress()
87: bridgeAgentExecutorAddress = IBridgeAgent(_bridgeAgentAddress).bridgeAgentExecutorAddress();
/// @audit getBridgeAgentManager()
112: if (msg.sender != IPort(rootPortAddress).getBridgeAgentManager(_rootBridgeAgent)) {
/// @audit getBranchBridgeAgent()
120: if (IBridgeAgent(_rootBridgeAgent).getBranchBridgeAgent(_dstChainId) != address(0)) revert InvalidChainId();
/// @audit factoryAddress()
130: IBridgeAgent(_rootBridgeAgent).factoryAddress(),
/// @audit name()
426: ERC20(_globalAddress).name(),
/// @audit symbol()
427: ERC20(_globalAddress).symbol(),
/// @audit decimals()
428: ERC20(_globalAddress).decimals(),
/// @audit createToken()
466: address newToken = address(IFactory(hTokenFactoryAddress).createToken(_name, _symbol, _decimals));
GitHub: 87, 112, 120, 130, 426, 427, 428, 466
File: src/MulticallRootRouter.sol
/// @audit bridgeAgentExecutorAddress()
113: bridgeAgentExecutorAddress = IBridgeAgent(_bridgeAgentAddress).bridgeAgentExecutorAddress();
/// @audit aggregate()
493: (blockNumber, returnData) = IMulticall(multicallAddress).aggregate(calls);
File: src/RootBridgeAgent.sol
/// @audit estimateFees()
146: (_fee,) = ILayerZeroEndpoint(lzEndpointAddress).estimateFees(
/// @audit getUserAccount()
248: if (msg.sender != address(IPort(localPortAddress).getUserAccount(settlementReference.owner))) {
/// @audit getUserAccount()
286: if (msg.sender != address(IPort(localPortAddress).getUserAccount(settlementOwner))) {
/// @audit getUserAccount()
312: if (msg.sender != address(IPort(localPortAddress).getUserAccount(settlementOwner))) {
/// @audit getLocalTokenFromUnderlying()
371: if (IPort(_localPortAddress).getLocalTokenFromUnderlying(_dParams.token, _srcChainId) != _dParams.hToken) {
/// @audit excessivelySafeCall()
424: (bool success,) = address(this).excessivelySafeCall(
/// @audit fetchVirtualAccount()
549: VirtualAccount userAccount = IPort(localPortAddress).fetchVirtualAccount(
/// @audit fetchVirtualAccount()
587: VirtualAccount userAccount = IPort(localPortAddress).fetchVirtualAccount(
/// @audit fetchVirtualAccount()
627: VirtualAccount userAccount = IPort(localPortAddress).fetchVirtualAccount(
/// @audit getUserAccount()
674: if (owner != address(IPort(localPortAddress).getUserAccount(settlementReference.owner))) {
/// @audit getLocalTokenFromGlobal()
981: address localAddress = IPort(localPortAddress).getLocalTokenFromGlobal(_globalAddress, _dstChainId);
/// @audit getUnderlyingTokenFromLocal()
984: address underlyingAddress = IPort(localPortAddress).getUnderlyingTokenFromLocal(localAddress, _dstChainId);
/// @audit getLocalTokenFromGlobal()
1072: hTokens[i] = IPort(localPortAddress).getLocalTokenFromGlobal(_globalAddresses[i], _dstChainId);
/// @audit getUnderlyingTokenFromLocal()
1073: tokens[i] = IPort(localPortAddress).getUnderlyingTokenFromLocal(hTokens[i], _dstChainId);
/// @audit getTokenBalance()
1158: if (IERC20hTokenRoot(_globalAddress).getTokenBalance(_dstChainId) < _deposit) {
/// @audit getBridgeAgentManager()
1233: if (msg.sender != IPort(localPortAddress).getBridgeAgentManager(address(this))) {
GitHub: 146, 248, 286, 312, 371, 424, 549, 587, 627, 674, 981, 984, 1072, 1073, 1158, 1233
File: src/RootPort.sol
/// @audit getBranchBridgeAgent()
398: if (IBridgeAgent(_rootBridgeAgent).getBranchBridgeAgent(_branchChainId) != address(0)) {
/// @audit createToken()
452: IERC20hTokenRootFactory(ICoreRootRouter(coreRootRouterAddress).hTokenFactoryAddress()).createToken(
File: src/factories/ERC20hTokenBranchFactory.sol
/// @audit name()
66: ERC20(_wrappedNativeTokenAddress).name(),
/// @audit symbol()
67: ERC20(_wrappedNativeTokenAddress).symbol(),
/// @audit decimals()
68: ERC20(_wrappedNativeTokenAddress).decimals(),
The instances below point to the second+ access of a state variable within a function. Caching of a state variable replaces each Gwarmaccess (100 gas) with a much cheaper stack read. Other less obvious fixes/optimizations include having local memory caches of state variable structs, or having local caches of state variable contracts/addresses.
There is one instance of this issue:
File: src/RootPort.sol
/// @audit coreRootRouterAddress on line 452
458: IBridgeAgent(ICoreRootRouter(coreRootRouterAddress).bridgeAgentAddress()).syncBranchBridgeAgent(
GitHub: 458
Not inlining costs 20 to 40 gas because of two extra JUMP
instructions and additional stack operations needed for function calls.
There are 14 instances of this issue:
see instances
File: src/ArbitrumCoreBranchRouter.sol
85 function _receiveAddBridgeAgent(
86 address _newBranchRouter,
87 address _branchBridgeAgentFactory,
88 address _rootBridgeAgent,
89 address _rootBridgeAgentFactory,
90 address _refundee,
91: GasParams memory _gParams
GitHub: 85
File: src/BaseBranchRouter.sol
186 function _transferAndApproveMultipleTokens(
187 address[] memory _hTokens,
188 address[] memory _tokens,
189 uint256[] memory _amounts,
190: uint256[] memory _deposits
GitHub: 186
File: src/BranchPort.sol
435: function _excessReserves(uint256 _strategyTokenDebt, address _token) internal view returns (uint256) {
449 function _reservesLacking(uint256 _strategyTokenDebt, address _token, uint256 currBalance)
450 internal
451 view
452: returns (uint256)
485: function _checkTimeLimit(address _token, uint256 _amount) internal {
File: src/CoreBranchRouter.sol
166 function _receiveAddGlobalToken(
167 address _globalAddress,
168 string memory _name,
169 string memory _symbol,
170 uint8 _decimals,
171 address _refundee,
172: GasParams memory _gParams
GitHub: 166
File: src/CoreRootRouter.sol
406 function _addGlobalToken(
407 address _refundee,
408 address _globalAddress,
409 uint16 _dstChainId,
410: GasParams[2] memory _gParams
452 function _addLocalToken(
453 address _underlyingAddress,
454 address _localAddress,
455 string memory _name,
456 string memory _symbol,
457 uint8 _decimals,
458: uint16 _srcChainId
481: function _setLocalToken(address _globalAddress, address _localAddress, uint16 _dstChainId) internal {
500: function _syncBranchBridgeAgent(address _newBranchBridgeAgent, address _rootBridgeAgent, uint256 _srcChainId)
File: src/MulticallRootRouter.sol
604 function _requiresExecutor() internal view {
605: if (msg.sender != bridgeAgentExecutorAddress) revert UnrecognizedBridgeAgentExecutor();
GitHub: 604
File: src/RootBridgeAgent.sol
966 function _createSettlement(
967 uint32 _settlementNonce,
968 address payable _refundee,
969 address _recipient,
970 uint16 _dstChainId,
971 bytes memory _params,
972 address _globalAddress,
973 uint256 _amount,
974 uint256 _deposit,
975 bool _hasFallbackToggled
976: ) internal returns (bytes memory _payload) {
1045 function _createSettlementMultiple(
1046 uint32 _settlementNonce,
1047 address payable _refundee,
1048 address _recipient,
1049 uint16 _dstChainId,
1050 address[] memory _globalAddresses,
1051 uint256[] memory _amounts,
1052 uint256[] memory _deposits,
1053 bytes memory _params,
1054 bool _hasFallbackToggled
1055: ) internal returns (bytes memory _payload) {
File: src/RootPort.sol
359: function addVirtualAccount(address _user) internal returns (VirtualAccount newAccount) {
GitHub: 359
The overheads outlined below are PER LOOP, excluding the first loop
- storage arrays incur a Gwarmaccess (100 gas)
- memory arrays use
MLOAD
(3 gas) - calldata arrays use
CALLDATALOAD
(3 gas)
Caching the length changes each of these to a DUP<N>
(3 gas), and gets rid of the extra DUP<N>
needed to store the stack offset
There are 8 instances of this issue:
File: src/BaseBranchRouter.sol
192: for (uint256 i = 0; i < _hTokens.length;) {
GitHub: 192
File: src/BranchBridgeAgent.sol
447: for (uint256 i = 0; i < deposit.tokens.length;) {
GitHub: 447
File: src/MulticallRootRouter.sol
278: for (uint256 i = 0; i < outputParams.outputTokens.length;) {
367: for (uint256 i = 0; i < outputParams.outputTokens.length;) {
455: for (uint256 i = 0; i < outputParams.outputTokens.length;) {
557: for (uint256 i = 0; i < outputTokens.length;) {
File: src/RootBridgeAgent.sol
318: for (uint256 i = 0; i < settlement.hTokens.length;) {
1070: for (uint256 i = 0; i < hTokens.length;) {
Each extra memory word of bytes past the original 32 incurs an MSTORE which costs 3 gas
There are 22 instances of this issue:
File: src/BranchBridgeAgent.sol
125: require(_rootBridgeAgentAddress != address(0), "Root Bridge Agent Address cannot be the zero address.");
126 require(
127 _lzEndpointAddress != address(0) || _rootChainId == _localChainId,
128 "Layerzero Endpoint Address cannot be the zero address."
129: );
130: require(_localRouterAddress != address(0), "Local Router Address cannot be the zero address.");
131: require(_localPortAddress != address(0), "Local Port Address cannot be the zero address.");
File: src/BranchPort.sol
127: require(_bridgeAgentFactory != address(0), "BridgeAgentFactory is zero address");
GitHub: 127
File: src/RootBridgeAgent.sol
111: require(_lzEndpointAddress != address(0), "Layerzero Enpoint Address cannot be zero address");
112: require(_localPortAddress != address(0), "Port Address cannot be zero address");
113: require(_localRouterAddress != address(0), "Router Address cannot be zero address");
File: src/RootPort.sol
130: require(_bridgeAgentFactory != address(0), "Bridge Agent Factory cannot be 0 address.");
131: require(_coreRootRouter != address(0), "Core Root Router cannot be 0 address.");
152: require(_coreRootBridgeAgent != address(0), "Core Root Bridge Agent cannot be 0 address.");
153: require(_coreLocalBranchBridgeAgent != address(0), "Core Local Branch Bridge Agent cannot be 0 address.");
154: require(_localBranchPortAddress != address(0), "Local Branch Port Address cannot be 0 address.");
GitHub: 130, 131, 152, 153, 154
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
57: require(_coreRootBridgeAgent != address(0), "Core Root Bridge Agent Address cannot be 0");
84 require(
85 msg.sender == localCoreBranchRouterAddress, "Only the Core Branch Router can create a new Bridge Agent."
86: );
87 require(
88 _rootBridgeAgentFactoryAddress == rootBridgeAgentFactoryAddress,
89 "Root Bridge Agent Factory Address does not match."
90: );
File: src/factories/BranchBridgeAgentFactory.sol
61: require(_rootBridgeAgentFactoryAddress != address(0), "Root Bridge Agent Factory Address cannot be 0");
62 require(
63 _lzEndpointAddress != address(0) || _rootChainId == _localChainId,
64 "Layerzero Endpoint Address cannot be the zero address."
65: );
66: require(_localCoreBranchRouterAddress != address(0), "Core Branch Router Address cannot be 0");
88: require(_coreRootBridgeAgent != address(0), "Core Root Bridge Agent cannot be 0");
120 require(
121 msg.sender == localCoreBranchRouterAddress, "Only the Core Branch Router can create a new Bridge Agent."
122: );
123 require(
124 _rootBridgeAgentFactoryAddress == rootBridgeAgentFactoryAddress,
125 "Root Bridge Agent Factory Address does not match."
126: );
GitHub: 61, 62, 66, 88, 120, 123
public
/external
function names and public
member variable names can be optimized to save gas. See this link for an example of how it works. Below are the interfaces/abstract contracts that can be optimized so that the most frequently-called functions use the least amount of gas possible during method lookup. Method IDs that have two leading zero bytes can save 128 gas each during deployment, and renaming functions to have lower method IDs will save 22 gas per call, per sorted position shifted
There are 24 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
/// @audit depositToPort(), withdrawFromPort()
31: contract ArbitrumBranchBridgeAgent is BranchBridgeAgent {
GitHub: 31
File: src/BranchBridgeAgentExecutor.sol
/// @audit executeNoSettlement(), executeWithSettlement(), executeWithSettlementMultiple()
29: contract BranchBridgeAgentExecutor is Ownable, BridgeAgentConstants {
GitHub: 29
File: src/CoreBranchRouter.sol
/// @audit addGlobalToken(), addLocalToken()
18: contract CoreBranchRouter is ICoreBranchRouter, BaseBranchRouter {
GitHub: 18
File: src/CoreRootRouter.sol
/// @audit initialize(), addBranchToBridgeAgent(), toggleBranchBridgeAgentFactory(), removeBranchBridgeAgent(), manageStrategyToken(), managePortStrategy(), setCoreBranch()
38: contract CoreRootRouter is IRootRouter, Ownable {
GitHub: 38
File: src/MulticallRootRouter.sol
/// @audit initialize(), executeDepositMultiple()
57: contract MulticallRootRouter is IRootRouter, Ownable {
GitHub: 57
File: src/RootBridgeAgent.sol
/// @audit getFeeEstimate(), retrieveSettlement(), lzReceive()
32: contract RootBridgeAgent is IRootBridgeAgent, BridgeAgentConstants {
GitHub: 32
File: src/RootBridgeAgentExecutor.sol
/// @audit executeSystemRequest(), executeNoDeposit(), executeWithDeposit(), executeWithDepositMultiple(), executeSignedNoDeposit(), executeSignedWithDeposit(), executeSignedWithDepositMultiple()
27: contract RootBridgeAgentExecutor is Ownable, BridgeAgentConstants {
GitHub: 27
File: src/RootPort.sol
/// @audit initialize(), initializeCore(), isLocalToken()
16: contract RootPort is Ownable, IRootPort {
GitHub: 16
File: src/factories/BranchBridgeAgentFactory.sol
/// @audit initialize(), createBridgeAgent()
19: contract BranchBridgeAgentFactory is Ownable, IBranchBridgeAgentFactory {
GitHub: 19
File: src/factories/ERC20hTokenBranchFactory.sol
/// @audit initialize(), getHTokens(), createToken()
12: contract ERC20hTokenBranchFactory is Ownable, IERC20hTokenBranchFactory {
GitHub: 12
File: src/factories/ERC20hTokenRootFactory.sol
/// @audit initialize(), getHTokens(), createToken()
12: contract ERC20hTokenRootFactory is Ownable, IERC20hTokenRootFactory {
GitHub: 12
File: src/interfaces/IArbitrumBranchPort.sol
/// @audit depositToPort(), withdrawFromPort()
16: interface IArbitrumBranchPort is IBranchPort {
GitHub: 16
File: src/interfaces/IBranchBridgeAgent.sol
/// @audit localPortAddress(), bridgeAgentExecutorAddress(), getDepositEntry(), getFeeEstimate(), callOutSystem(), callOut(), callOutAndBridge(), callOutAndBridgeMultiple(), callOutSigned(), callOutSignedAndBridge(), callOutSignedAndBridgeMultiple(), retryDeposit(), retrieveDeposit(), redeemDeposit(), retrySettlement(), clearToken(), clearTokens(), lzReceiveNonBlocking()
87: interface IBranchBridgeAgent is ILayerZeroReceiver {
GitHub: 87
File: src/interfaces/IBranchPort.sol
/// @audit isBridgeAgent(), isStrategyToken(), isPortStrategy(), isBridgeAgentFactory(), manage(), replenishReserves(), replenishReserves(), withdraw(), bridgeIn(), bridgeInMultiple(), bridgeOut(), bridgeOutMultiple(), addBridgeAgent(), setCoreRouter(), addBridgeAgentFactory(), toggleBridgeAgentFactory(), toggleBridgeAgent(), addStrategyToken(), toggleStrategyToken(), addPortStrategy(), togglePortStrategy(), updatePortStrategy(), setCoreBranchRouter()
14: interface IBranchPort {
GitHub: 14
File: src/interfaces/IBranchRouter.sol
/// @audit localPortAddress(), localBridgeAgentAddress(), bridgeAgentExecutorAddress(), callOut(), callOutAndBridge(), callOutAndBridgeMultiple(), getDepositEntry(), executeNoSettlement(), executeSettlement(), executeSettlementMultiple()
21: interface IBranchRouter {
GitHub: 21
File: src/interfaces/ICoreBranchRouter.sol
/// @audit addGlobalToken(), addLocalToken()
27: interface ICoreBranchRouter {
GitHub: 27
File: src/interfaces/IERC20hTokenRoot.sol
/// @audit localChainId(), factoryAddress(), getTokenBalance(), burn()
12: interface IERC20hTokenRoot {
GitHub: 12
File: src/interfaces/ILayerZeroEndpoint.sol
/// @audit send(), receivePayload(), getInboundNonce(), getOutboundNonce(), estimateFees(), getChainId(), retryPayload(), hasStoredPayload(), getSendLibraryAddress(), getReceiveLibraryAddress(), isSendingPayload(), isReceivingPayload(), getConfig(), getSendVersion(), getReceiveVersion()
7: interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
GitHub: 7
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
/// @audit setConfig(), setSendVersion(), setReceiveVersion(), forceResumeReceive()
5: interface ILayerZeroUserApplicationConfig {
GitHub: 5
File: src/interfaces/IRootBridgeAgent.sol
/// @audit settlementNonce(), getSettlementEntry(), bridgeAgentExecutorAddress(), factoryAddress(), getBranchBridgeAgent(), isBranchBridgeAgentAllowed(), getFeeEstimate(), callOut(), callOutAndBridge(), callOutAndBridgeMultiple(), retrySettlement(), retrieveSettlement(), redeemSettlement(), bridgeIn(), bridgeInMultiple(), lzReceiveNonBlocking(), approveBranchBridgeAgent(), syncBranchBridgeAgent()
94: interface IRootBridgeAgent is ILayerZeroReceiver {
GitHub: 94
File: src/interfaces/IRootPort.sol
/// @audit bridgeAgentAddress(), hTokenFactoryAddress(), setCoreBranch()
10: interface ICoreRootRouter {
/// @audit isChainId(), getBridgeAgentManager(), isBridgeAgentFactory(), isGlobalAddress(), getGlobalTokenFromLocal(), getLocalTokenFromGlobal(), getLocalTokenFromUnderlying(), getLocalToken(), getUnderlyingTokenFromLocal(), getUnderlyingTokenFromGlobal(), isGlobalToken(), isLocalToken(), isLocalToken(), isUnderlyingToken(), getUserAccount(), isRouterApproved(), bridgeToRoot(), bridgeToRootFromLocalBranch(), bridgeToLocalBranchFromRoot(), mintToLocalBranch(), burnFromLocalBranch(), setAddresses(), setLocalAddress(), fetchVirtualAccount(), toggleVirtualAccountApproved(), syncBranchBridgeAgentWithRoot(), addBridgeAgent(), toggleBridgeAgent(), addBridgeAgentFactory(), toggleBridgeAgentFactory(), addNewChain(), addEcosystemToken(), setCoreRootRouter(), setCoreBranchRouter(), syncNewCoreBranchRouter()
31: interface IRootPort {
File: src/interfaces/IRootRouter.sol
/// @audit executeResponse(), execute(), executeDepositSingle(), executeDepositMultiple(), executeSigned(), executeSignedDepositSingle(), executeSignedDepositMultiple()
14: interface IRootRouter {
GitHub: 14
File: src/interfaces/IVirtualAccount.sol
/// @audit userAddress(), localPortAddress(), withdrawNative(), withdrawERC20(), withdrawERC721(), call(), payableCall()
27: interface IVirtualAccount is IERC721Receiver {
GitHub: 27
Saves 5 gas per loop
There is one instance of this issue:
File: src/BranchPort.sol
309: i++;
GitHub: 309
When using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.
https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html
Each operation involving a uint8
costs an extra 22-28 gas (depending on whether the other operand is also a variable of type uint8
) as compared to ones involving uint256
, due to the compiler having to clear the higher bits of the memory word before operating on the uint8
, as well as the associated stack operations of doing so. Use a larger size then downcast where needed
There are 21 instances of this issue:
File: src/BranchBridgeAgent.sol
/// @audit uint32 depositNonce
140: depositNonce = 1;
/// @audit uint32 nonce
601: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));
/// @audit uint32 nonce
621: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));
/// @audit uint32 nonce
643: nonce = uint32(bytes4(_payload[22:26]));
/// @audit uint32 nonce
668: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));
/// @audit uint32 nonce
683: nonce = uint32(bytes4(_payload[PARAMS_START:PARAMS_TKN_START]));
/// @audit uint32 depositNonce
821: depositNonce = _depositNonce + 1;
/// @audit uint32 depositNonce
875: depositNonce = _depositNonce + 1;
GitHub: 140, 601, 621, 643, 668, 683, 821, 875
File: src/RootBridgeAgent.sol
/// @audit uint32 settlementNonce
121: settlementNonce = 1;
/// @audit uint32 nonce
446: nonce = uint32(bytes4(_payload[PARAMS_START:PARAMS_TKN_START]));
/// @audit uint32 nonce
469: nonce = uint32(bytes4(_payload[PARAMS_START:PARAMS_TKN_START]));
/// @audit uint32 nonce
492: nonce = uint32(bytes4(_payload[PARAMS_START:PARAMS_TKN_START]));
/// @audit uint32 nonce
515: nonce = uint32(bytes4(_payload[2:6]));
/// @audit uint32 nonce
541: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));
/// @audit uint32 nonce
579: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));
/// @audit uint32 nonce
619: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED + PARAMS_START:PARAMS_START_SIGNED + PARAMS_TKN_START]));
/// @audit uint32 nonce
701: nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));
/// @audit uint32 nonce
720: nonce = uint32(bytes4(_payload[PARAMS_START:PARAMS_TKN_START]));
/// @audit uint32 settlementNonce
978: settlementNonce = _settlementNonce + 1;
/// @audit uint32 settlementNonce
1064: settlementNonce = _settlementNonce + 1;
GitHub: 121, 446, 469, 492, 515, 541, 579, 619, 701, 720, 978, 1064
File: src/factories/ERC20hTokenBranchFactory.sol
/// @audit uint24 localChainId
46: localChainId = _localChainId;
GitHub: 46
If needed, the values can be read from the verified contract source code, or if there are multiple values there can be a single getter function that returns a tuple of the values of all currently-public constants. Saves 3406-3606 gas in deployment gas due to the compiler not having to create non-payable getter functions for deployment calldata, not having to store the bytes of the value outside of where it's used, and not adding another entry to the method ID table
There are 12 instances of this issue:
see instances
File: src/ArbitrumBranchPort.sol
22: uint16 public immutable localChainId;
GitHub: 22
File: src/BranchBridgeAgent.sol
53: uint16 public immutable rootChainId;
56: uint16 public immutable localChainId;
File: src/CoreRootRouter.sol
47: uint256 public immutable rootChainId;
GitHub: 47
File: src/MulticallRootRouter.sol
65: uint256 public immutable localChainId;
GitHub: 65
File: src/RootBridgeAgent.sol
40: uint16 public immutable localChainId;
GitHub: 40
File: src/RootPort.sol
34: uint256 public immutable localChainId;
GitHub: 34
File: src/factories/BranchBridgeAgentFactory.sol
21: uint16 public immutable localChainId;
24: uint16 public immutable rootChainId;
File: src/factories/ERC20hTokenBranchFactory.sol
14: uint24 public immutable localChainId;
GitHub: 14
File: src/factories/ERC20hTokenRootFactory.sol
14: uint16 public immutable localChainId;
GitHub: 14
File: src/factories/RootBridgeAgentFactory.sol
13: uint16 public immutable rootChainId;
GitHub: 13
Flipping the true
and false
blocks instead saves 3 gas
There is one instance of this issue:
File: src/CoreBranchRouter.sol
317 if (!IPort(_localPortAddress).isPortStrategy(_portStrategy, _underlyingToken)) {
318 // If Port Strategy is not active, add new Port Strategy.
319 IPort(_localPortAddress).addPortStrategy(_portStrategy, _underlyingToken, _dailyManagementLimit);
320 } else if (_isUpdateDailyLimit) {
321 // Or update daily limit.
322 IPort(_localPortAddress).updatePortStrategy(_portStrategy, _underlyingToken, _dailyManagementLimit);
323 } else {
324 // Or Toggle Port Strategy.
325 IPort(_localPortAddress).togglePortStrategy(_portStrategy, _underlyingToken);
326: }
GitHub: 317
[G‑14] require()
or revert()
statements that check input arguments should be at the top of the function
Checks that involve constants should come before checks that involve state variables, function calls, and calculations. By doing these checks first, the function is able to revert before wasting a Gcoldsload (2100 gas*) in a function that may ultimately revert in the unhappy case.
There are 11 instances of this issue:
File: src/BranchBridgeAgent.sol
/// @audit expensive op on line 127
130: require(_localRouterAddress != address(0), "Local Router Address cannot be the zero address.");
/// @audit expensive op on line 127
131: require(_localPortAddress != address(0), "Local Port Address cannot be the zero address.");
File: src/BranchPort.sol
/// @audit expensive op on line 124
126: require(_coreBranchRouter != address(0), "CoreBranchRouter is zero address");
/// @audit expensive op on line 124
127: require(_bridgeAgentFactory != address(0), "BridgeAgentFactory is zero address");
/// @audit expensive op on line 178
181: require(ERC20(_token).balanceOf(address(this)) - currBalance == _amount, "Port Strategy Withdraw Failed");
/// @audit expensive op on line 332
333: require(_newCoreRouter != address(0), "New CoreRouter address is zero");
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
/// @audit expensive op on line 85
87 require(
88 _rootBridgeAgentFactoryAddress == rootBridgeAgentFactoryAddress,
89 "Root Bridge Agent Factory Address does not match."
90: );
GitHub: 87
File: src/factories/BranchBridgeAgentFactory.sol
/// @audit expensive op on line 63
66: require(_localCoreBranchRouterAddress != address(0), "Core Branch Router Address cannot be 0");
/// @audit expensive op on line 63
67: require(_localPortAddress != address(0), "Port Address cannot be 0");
/// @audit expensive op on line 63
68: require(_owner != address(0), "Owner cannot be 0");
/// @audit expensive op on line 121
123 require(
124 _rootBridgeAgentFactoryAddress == rootBridgeAgentFactoryAddress,
125 "Root Bridge Agent Factory Address does not match."
126: );
Custom errors are available from solidity version 0.8.4. Custom errors save ~50 gas each time they're hit by avoiding having to allocate and store the revert string. Not defining the strings also save deployment gas
There are 49 instances of this issue:
see instances
File: src/ArbitrumBranchPort.sol
39: require(_rootPortAddress != address(0), "Root Port Address cannot be 0");
GitHub: 39
File: src/BaseBranchRouter.sol
61: require(_localBridgeAgentAddress != address(0), "Bridge Agent address cannot be 0");
GitHub: 61
File: src/BranchBridgeAgent.sol
125: require(_rootBridgeAgentAddress != address(0), "Root Bridge Agent Address cannot be the zero address.");
126 require(
127 _lzEndpointAddress != address(0) || _rootChainId == _localChainId,
128 "Layerzero Endpoint Address cannot be the zero address."
129: );
130: require(_localRouterAddress != address(0), "Local Router Address cannot be the zero address.");
131: require(_localPortAddress != address(0), "Local Port Address cannot be the zero address.");
File: src/BranchPort.sol
109: require(_owner != address(0), "Owner is zero address");
123: require(coreBranchRouterAddress == address(0), "Contract already initialized");
124: require(!isBridgeAgentFactory[_bridgeAgentFactory], "Contract already initialized");
126: require(_coreBranchRouter != address(0), "CoreBranchRouter is zero address");
127: require(_bridgeAgentFactory != address(0), "BridgeAgentFactory is zero address");
181: require(ERC20(_token).balanceOf(address(this)) - currBalance == _amount, "Port Strategy Withdraw Failed");
213 require(
214 ERC20(_token).balanceOf(address(this)) - currBalance == amountToWithdraw, "Port Strategy Withdraw Failed"
215: );
332: require(coreBranchRouterAddress != address(0), "CoreRouter address is zero");
333: require(_newCoreRouter != address(0), "New CoreRouter address is zero");
GitHub: 109, 123, 124, 126, 127, 181, 213, 332, 333
File: src/CoreRootRouter.sol
84: require(_setup, "Contract is already initialized");
278: require(msg.sender == rootPortAddress, "Only root port can call");
File: src/MulticallRootRouter.sol
93: require(_localPortAddress != address(0), "Local Port Address cannot be 0");
94: require(_multicallAddress != address(0), "Multicall Address cannot be 0");
110: require(_bridgeAgentAddress != address(0), "Bridge Agent Address cannot be 0");
File: src/RootBridgeAgent.sol
111: require(_lzEndpointAddress != address(0), "Layerzero Enpoint Address cannot be zero address");
112: require(_localPortAddress != address(0), "Port Address cannot be zero address");
113: require(_localRouterAddress != address(0), "Router Address cannot be zero address");
File: src/RootPort.sol
130: require(_bridgeAgentFactory != address(0), "Bridge Agent Factory cannot be 0 address.");
131: require(_coreRootRouter != address(0), "Core Root Router cannot be 0 address.");
132: require(_setup, "Setup ended.");
152: require(_coreRootBridgeAgent != address(0), "Core Root Bridge Agent cannot be 0 address.");
153: require(_coreLocalBranchBridgeAgent != address(0), "Core Local Branch Bridge Agent cannot be 0 address.");
154: require(_localBranchPortAddress != address(0), "Local Branch Port Address cannot be 0 address.");
155: require(isBridgeAgent[_coreRootBridgeAgent], "Core Bridge Agent doesn't exist.");
156: require(_setupCore, "Core Setup ended.");
GitHub: 130, 131, 132, 152, 153, 154, 155, 156
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
57: require(_coreRootBridgeAgent != address(0), "Core Root Bridge Agent Address cannot be 0");
84 require(
85 msg.sender == localCoreBranchRouterAddress, "Only the Core Branch Router can create a new Bridge Agent."
86: );
87 require(
88 _rootBridgeAgentFactoryAddress == rootBridgeAgentFactoryAddress,
89 "Root Bridge Agent Factory Address does not match."
90: );
File: src/factories/BranchBridgeAgentFactory.sol
61: require(_rootBridgeAgentFactoryAddress != address(0), "Root Bridge Agent Factory Address cannot be 0");
62 require(
63 _lzEndpointAddress != address(0) || _rootChainId == _localChainId,
64 "Layerzero Endpoint Address cannot be the zero address."
65: );
66: require(_localCoreBranchRouterAddress != address(0), "Core Branch Router Address cannot be 0");
67: require(_localPortAddress != address(0), "Port Address cannot be 0");
68: require(_owner != address(0), "Owner cannot be 0");
88: require(_coreRootBridgeAgent != address(0), "Core Root Bridge Agent cannot be 0");
120 require(
121 msg.sender == localCoreBranchRouterAddress, "Only the Core Branch Router can create a new Bridge Agent."
122: );
123 require(
124 _rootBridgeAgentFactoryAddress == rootBridgeAgentFactoryAddress,
125 "Root Bridge Agent Factory Address does not match."
126: );
GitHub: 61, 62, 66, 67, 68, 88, 120, 123
File: src/factories/ERC20hTokenBranchFactory.sol
43: require(_localPortAddress != address(0), "Port address cannot be 0");
61: require(_coreRouter != address(0), "CoreRouter address cannot be 0");
File: src/factories/ERC20hTokenRootFactory.sol
35: require(_rootPortAddress != address(0), "Root Port Address cannot be 0");
50: require(_coreRouter != address(0), "CoreRouter address cannot be 0");
File: src/factories/RootBridgeAgentFactory.sol
32: require(_rootPortAddress != address(0), "Root Port Address cannot be 0");
GitHub: 32
File: src/token/ERC20hTokenRoot.sol
39: require(_rootPortAddress != address(0), "Root Port Address cannot be 0");
40: require(_factoryAddress != address(0), "Factory Address cannot be 0");
If a function modifier such as onlyOwner
is used, the function will revert if a normal user tries to pay the function. Marking the function as payable
will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided. The extra opcodes avoided are
CALLVALUE
(2),DUP1
(3),ISZERO
(3),PUSH2
(3),JUMPI
(10),PUSH1
(3),DUP1
(3),REVERT
(0),JUMPDEST
(1),POP
(2), which costs an average of about 21 gas per call to the function, in addition to the extra deployment cost
There are 21 instances of this issue:
see instances
File: src/BaseBranchRouter.sol
60: function initialize(address _localBridgeAgentAddress) external onlyOwner {
GitHub: 60
File: src/BranchPort.sol
122: function initialize(address _coreBranchRouter, address _bridgeAgentFactory) external virtual onlyOwner {
GitHub: 122
File: src/CoreRootRouter.sol
83: function initialize(address _bridgeAgentAddress, address _hTokenFactory) external onlyOwner {
GitHub: 83
File: src/MulticallRootRouter.sol
109: function initialize(address _bridgeAgentAddress) external onlyOwner {
GitHub: 109
File: src/RootPort.sol
129: function initialize(address _bridgeAgentFactory, address _coreRootRouter) external onlyOwner {
147 function initializeCore(
148 address _coreRootBridgeAgent,
149 address _coreLocalBranchBridgeAgent,
150 address _localBranchPortAddress
151: ) external onlyOwner {
414: function toggleBridgeAgent(address _bridgeAgent) external override onlyOwner {
421: function addBridgeAgentFactory(address _bridgeAgentFactory) external override onlyOwner {
431: function toggleBridgeAgentFactory(address _bridgeAgentFactory) external override onlyOwner {
438 function addNewChain(
439 address _coreBranchBridgeAgentAddress,
440 uint256 _chainId,
441 string memory _wrappedGasTokenName,
442 string memory _wrappedGasTokenSymbol,
443 uint8 _wrappedGasTokenDecimals,
444 address _newLocalBranchWrappedNativeTokenAddress,
445 address _newUnderlyingBranchWrappedNativeTokenAddress
446: ) external override onlyOwner {
483: function addEcosystemToken(address _ecoTokenGlobalAddress) external override onlyOwner {
509: function setCoreRootRouter(address _coreRootRouter, address _coreRootBridgeAgent) external override onlyOwner {
539 function syncNewCoreBranchRouter(address _coreBranchRouter, address _coreBranchBridgeAgent, uint16 _dstChainId)
540 external
541 override
542: onlyOwner
GitHub: 129, 147, 414, 421, 431, 438, 483, 509, 539
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
56: function initialize(address _coreRootBridgeAgent) external override onlyOwner {
GitHub: 56
File: src/factories/BranchBridgeAgentFactory.sol
87: function initialize(address _coreRootBridgeAgent) external virtual onlyOwner {
GitHub: 87
File: src/factories/ERC20hTokenBranchFactory.sol
60: function initialize(address _wrappedNativeTokenAddress, address _coreRouter) external onlyOwner {
GitHub: 60
File: src/factories/ERC20hTokenRootFactory.sol
49: function initialize(address _coreRouter) external onlyOwner {
GitHub: 49
File: src/token/ERC20hTokenBranch.sol
29: function mint(address account, uint256 amount) external override onlyOwner returns (bool) {
35: function burn(uint256 amount) public override onlyOwner {
File: src/token/ERC20hTokenRoot.sol
57: function mint(address to, uint256 amount, uint256 chainId) external onlyOwner returns (bool) {
69: function burn(address from, uint256 amount, uint256 chainId) external onlyOwner {
Payable functions cost less gas to execute, since the compiler does not have to add extra checks to ensure that a payment wasn't provided. A constructor can safely be marked as payable, since only the deployer would be able to pass funds, and the project itself would not pass any funds.
There are 22 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
43 constructor(
44 uint16 _localChainId,
45 address _rootBridgeAgentAddress,
46 address _localRouterAddress,
47 address _localPortAddress
48 )
49 BranchBridgeAgent(
50 _localChainId,
51 _localChainId,
52 _rootBridgeAgentAddress,
53 address(0),
54 _localRouterAddress,
55 _localPortAddress
56: )
GitHub: 43
File: src/ArbitrumBranchPort.sol
38: constructor(uint16 _localChainId, address _rootPortAddress, address _owner) BranchPort(_owner) {
GitHub: 38
File: src/ArbitrumCoreBranchRouter.sol
44: constructor() CoreBranchRouter(address(0)) {}
GitHub: 44
File: src/BaseBranchRouter.sol
48 constructor() {
49: _initializeOwner(msg.sender);
GitHub: 48
File: src/BranchBridgeAgent.sol
117 constructor(
118 uint16 _rootChainId,
119 uint16 _localChainId,
120 address _rootBridgeAgentAddress,
121 address _lzEndpointAddress,
122 address _localRouterAddress,
123: address _localPortAddress
GitHub: 117
File: src/BranchBridgeAgentExecutor.sol
39 constructor() {
40: _initializeOwner(msg.sender);
GitHub: 39
File: src/BranchPort.sol
108: constructor(address _owner) {
GitHub: 108
File: src/CoreBranchRouter.sol
30: constructor(address _hTokenFactoryAddress) BaseBranchRouter() {
GitHub: 30
File: src/CoreRootRouter.sol
71: constructor(uint256 _rootChainId, address _rootPortAddress) {
GitHub: 71
File: src/MulticallRootRouter.sol
92: constructor(uint256 _localChainId, address _localPortAddress, address _multicallAddress) {
GitHub: 92
File: src/MulticallRootRouterLibZip.sol
29 constructor(uint256 _localChainId, address _localPortAddress, address _multicallAddress)
30: MulticallRootRouter(_localChainId, _localPortAddress, _multicallAddress)
GitHub: 29
File: src/RootBridgeAgent.sol
105 constructor(
106 uint16 _localChainId,
107 address _lzEndpointAddress,
108 address _localPortAddress,
109: address _localRouterAddress
GitHub: 105
File: src/RootBridgeAgentExecutor.sol
35: constructor(address _rootBridgeAgent) {
GitHub: 35
File: src/RootPort.sol
111: constructor(uint256 _localChainId) {
GitHub: 111
File: src/VirtualAccount.sol
35: constructor(address _userAddress, address _localPortAddress) {
GitHub: 35
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
30 constructor(
31 uint16 _rootChainId,
32 address _rootBridgeAgentFactoryAddress,
33 address _localCoreBranchRouterAddress,
34 address _localPortAddress,
35 address _owner
36 )
37 BranchBridgeAgentFactory(
38 _rootChainId,
39 _rootChainId,
40 _rootBridgeAgentFactoryAddress,
41 address(0),
42 _localCoreBranchRouterAddress,
43 _localPortAddress,
44 _owner
45: )
GitHub: 30
File: src/factories/BranchBridgeAgentFactory.sol
52 constructor(
53 uint16 _localChainId,
54 uint16 _rootChainId,
55 address _rootBridgeAgentFactoryAddress,
56 address _lzEndpointAddress,
57 address _localCoreBranchRouterAddress,
58 address _localPortAddress,
59: address _owner
GitHub: 52
File: src/factories/ERC20hTokenBranchFactory.sol
42: constructor(uint16 _localChainId, address _localPortAddress, string memory _chainName, string memory _chainSymbol) {
GitHub: 42
File: src/factories/ERC20hTokenRootFactory.sol
34: constructor(uint16 _localChainId, address _rootPortAddress) {
GitHub: 34
File: src/factories/RootBridgeAgentFactory.sol
31: constructor(uint16 _rootChainId, address _lzEndpointAddress, address _rootPortAddress) {
GitHub: 31
File: src/token/ERC20hTokenBranch.sol
13 constructor(
14 string memory chainName,
15 string memory chainSymbol,
16 string memory _name,
17 string memory _symbol,
18 uint8 _decimals,
19 address _owner
20: ) ERC20(string(string.concat(chainName, _name)), string(string.concat(chainSymbol, _symbol)), _decimals) {
GitHub: 13
File: src/token/ERC20hTokenRoot.sol
31 constructor(
32 uint16 _localChainId,
33 address _factoryAddress,
34 address _rootPortAddress,
35 string memory _name,
36 string memory _symbol,
37 uint8 _decimals
38: ) ERC20(string(string.concat(_name)), string(string.concat(_symbol)), _decimals) {
GitHub: 31
See this link for the full details
There are 44 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/ArbitrumBranchPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/ArbitrumCoreBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BaseBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BranchBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BranchBridgeAgentExecutor.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BranchPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/CoreBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/CoreRootRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/MulticallRootRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/MulticallRootRouterLibZip.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/RootBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/RootBridgeAgentExecutor.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/RootPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/VirtualAccount.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/BranchBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/ERC20hTokenBranchFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/ERC20hTokenRootFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/RootBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/BridgeAgentConstants.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/BridgeAgentStructs.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IArbitrumBranchPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/interfaces/IBranchBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IBranchBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IBranchPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/interfaces/IBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/ICoreBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IERC20hTokenBranch.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IERC20hTokenBranchFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IERC20hTokenRoot.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IERC20hTokenRootFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/ILayerZeroEndpoint.sol
3: pragma solidity >=0.5.0;
GitHub: 3
File: src/interfaces/ILayerZeroReceiver.sol
3: pragma solidity >=0.5.0;
GitHub: 3
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
3: pragma solidity >=0.5.0;
GitHub: 3
File: src/interfaces/IMulticall2.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IPortStrategy.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/interfaces/IRootBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IRootBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IRootPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/interfaces/IRootRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IVirtualAccount.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/token/ERC20hTokenBranch.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/token/ERC20hTokenRoot.sol
2: pragma solidity ^0.8.0;
GitHub: 2
The compiler uses opcodes GT
and ISZERO
for solidity code that uses >
, but only requires LT
for >=
, which saves 3 gas. If <
is being used, the condition can be inverted.
There are 33 instances of this issue:
see instances
File: src/ArbitrumBranchPort.sol
127: if (_deposit > 0) {
132: if (_amount - _deposit > 0) {
File: src/BaseBranchRouter.sol
165: if (_amount - _deposit > 0) {
173: if (_deposit > 0) {
File: src/BranchBridgeAgent.sol
383: } else if (uint8(deposit.hTokens.length) > 1) {
869: if (_hTokens.length > MAX_TOKENS_LENGTH) revert InvalidInput();
906: if (_amount - _deposit > 0) {
912: if (_deposit > 0) {
File: src/BranchBridgeAgentExecutor.sol
87: if (_payload.length > PARAMS_SETTLEMENT_OFFSET) {
119: if (_payload.length > settlementEndOffset) {
File: src/BranchPort.sol
149: if (_amount > _excessReserves(_strategyTokenDebt, _token)) revert InsufficientReserves();
259: if (_amounts[i] - _deposits[i] > 0) {
266: if (_deposits[i] > 0) {
299: if (length > 255) revert InvalidInputArrays();
525: if (_hTokenAmount > 0) {
531: if (_deposit > 0) {
GitHub: 149, 259, 266, 299, 525, 531
File: src/RootBridgeAgent.sol
357: if (_dParams.amount < _dParams.deposit) revert InvalidInputParams();
363: if (_dParams.amount > 0) {
370: if (_dParams.deposit > 0) {
396: if (length > MAX_TOKENS_LENGTH) revert InvalidInputParams();
891: } else if (_hTokens.length > 1) {
1057: if (_globalAddresses.length > MAX_TOKENS_LENGTH) revert InvalidInputParamsLength();
1142: if (_amount < _deposit) revert InvalidInputParams();
1146: if (_underlyingAddress == address(0)) if (_deposit > 0) revert UnrecognizedUnderlyingAddress();
1149: if (_amount - _deposit > 0) {
1156: if (_deposit > 0) {
1158: if (IERC20hTokenRoot(_globalAddress).getTokenBalance(_dstChainId) < _deposit) {
GitHub: 357, 363, 370, 396, 891, 1057, 1142, 1146, 1149, 1156, 1158
File: src/RootBridgeAgentExecutor.sol
100: if (_payload.length > PARAMS_TKN_SET_SIZE) {
134: if (length > PARAMS_END_OFFSET + (numOfAssets * PARAMS_TKN_SET_SIZE_MULTIPLE)) {
185: if (_payload.length > PARAMS_SETTLEMENT_OFFSET) {
220 _payload.length
221 > PARAMS_END_SIGNED_OFFSET
222: + uint256(uint8(bytes1(_payload[PARAMS_START_SIGNED]))) * PARAMS_TKN_SET_SIZE_MULTIPLE
File: src/RootPort.sol
284: if (_amount - _deposit > 0) {
290: if (_deposit > 0) if (!ERC20hTokenRoot(_hToken).mint(_recipient, _deposit, _srcChainId)) revert UnableToMint();
Nesting if
-statements avoids the stack operations of setting up and using an extra jumpdest
, and saves 6 gas
There is one instance of this issue:
File: src/RootBridgeAgent.sol
1141: if (_amount == 0 && _deposit == 0) revert InvalidInputParams();
GitHub: 1141
Using the scratch space for event arguments (two words or fewer) will save gas over needing Solidity's full abi memory expansion used for emitting normally.
There are 19 instances of this issue:
File: src/BranchBridgeAgent.sol
689: emit LogFallback(nonce);
700: emit LogExecute(nonce);
File: src/BranchPort.sol
344: emit BridgeAgentFactoryAdded(_newBridgeAgentFactory);
351: emit BridgeAgentFactoryToggled(_newBridgeAgentFactory);
358: emit BridgeAgentToggled(_bridgeAgent);
371: emit StrategyTokenAdded(_token, _minimumReservesRatio);
378: emit StrategyTokenToggled(_token);
399: emit PortStrategyToggled(_portStrategy, _token);
423: emit CoreBranchSet(_coreBranchRouter, _coreBranchBridgeAgent);
GitHub: 344, 351, 358, 371, 378, 399, 423
File: src/RootBridgeAgent.sol
726: emit LogFallback(nonce, _srcChainId);
736: emit LogExecute(nonce, _srcChainId);
File: src/RootPort.sol
365: emit VirtualAccountCreated(_user, address(newAccount));
389: emit BridgeAgentAdded(_bridgeAgent, _manager);
417: emit BridgeAgentToggled(_bridgeAgent);
427: emit BridgeAgentFactoryAdded(_bridgeAgentFactory);
434: emit BridgeAgentFactoryToggled(_bridgeAgentFactory);
479: emit NewChainAdded(_chainId);
505: emit EcosystemTokenAdded(_ecoTokenGlobalAddress);
517: emit CoreRootSet(_coreRootRouter, _coreRootBridgeAgent);
GitHub: 365, 389, 417, 427, 434, 479, 505, 517
Using +=
for mappings saves 40 gas due to not having to recalculate the mapping's value's hash
There are 5 instances of this issue:
File: src/BranchPort.sol
349: isBridgeAgentFactory[_newBridgeAgentFactory] = !isBridgeAgentFactory[_newBridgeAgentFactory];
356: isBridgeAgent[_bridgeAgent] = !isBridgeAgent[_bridgeAgent];
376: isStrategyToken[_token] = !isStrategyToken[_token];
File: src/RootPort.sol
415: isBridgeAgent[_bridgeAgent] = !isBridgeAgent[_bridgeAgent];
432: isBridgeAgentFactory[_bridgeAgentFactory] = !isBridgeAgentFactory[_bridgeAgentFactory];
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/58f635312aa21f947cae5f8578638a85aa2519f5/contracts/security/ReentrancyGuard.sol#L23-L27
Use uint256(0)
and uint256(1)
for true/false to avoid a Gwarmaccess (100 gas) for the extra SLOAD
There are 13 instances of this issue:
File: src/BranchPort.sol
32: mapping(address bridgeAgent => bool isActiveBridgeAgent) public isBridgeAgent;
42: mapping(address bridgeAgentFactory => bool isActiveBridgeAgentFactory) public isBridgeAgentFactory;
52: mapping(address token => bool allowsStrategies) public isStrategyToken;
68: mapping(address strategy => mapping(address token => bool isActiveStrategy)) public isPortStrategy;
File: src/CoreRootRouter.sol
44: bool internal _setup;
GitHub: 44
File: src/RootBridgeAgent.sol
68: mapping(uint256 chainId => bool allowed) public isBranchBridgeAgentAllowed;
GitHub: 68
File: src/RootPort.sol
24: bool internal _setup;
27: bool internal _setupCore;
54: mapping(VirtualAccount acount => mapping(address router => bool allowed)) public isRouterApproved;
61: mapping(uint256 chainId => bool isActive) public isChainId;
64: mapping(address bridgeAgent => bool isActive) public isBridgeAgent;
77: mapping(address bridgeAgentFactory => bool isActive) public isBridgeAgentFactory;
87: mapping(address token => bool isGlobalToken) public isGlobalAddress;
GitHub: 24, 27, 54, 61, 64, 77, 87
Avoids a Gsset (20000 gas) when changing from false
to true
, after having been true
in the past
There are 13 instances of this issue:
File: src/BranchPort.sol
32: mapping(address bridgeAgent => bool isActiveBridgeAgent) public isBridgeAgent;
42: mapping(address bridgeAgentFactory => bool isActiveBridgeAgentFactory) public isBridgeAgentFactory;
52: mapping(address token => bool allowsStrategies) public isStrategyToken;
68: mapping(address strategy => mapping(address token => bool isActiveStrategy)) public isPortStrategy;
File: src/CoreRootRouter.sol
44: bool internal _setup;
GitHub: 44
File: src/RootBridgeAgent.sol
68: mapping(uint256 chainId => bool allowed) public isBranchBridgeAgentAllowed;
GitHub: 68
File: src/RootPort.sol
24: bool internal _setup;
27: bool internal _setupCore;
54: mapping(VirtualAccount acount => mapping(address router => bool allowed)) public isRouterApproved;
61: mapping(uint256 chainId => bool isActive) public isChainId;
64: mapping(address bridgeAgent => bool isActive) public isBridgeAgent;
77: mapping(address bridgeAgentFactory => bool isActive) public isBridgeAgentFactory;
87: mapping(address token => bool isGlobalToken) public isGlobalAddress;
GitHub: 24, 27, 54, 61, 64, 77, 87
There are 25 instances of this issue:
File: src/ArbitrumBranchPort.sol
63: if (_globalToken == address(0)) revert UnknownGlobalToken();
90: if (_underlyingAddress == address(0)) revert UnknownUnderlyingToken();
File: src/BranchBridgeAgent.sol
412: if (payload.length == 0) revert DepositRetryUnavailableUseCallout();
440: if (deposit.owner == address(0)) revert DepositRedeemUnavailable();
File: src/RootBridgeAgent.sol
244: if (settlementReference.owner == address(0)) revert SettlementRetryUnavailable();
282: if (settlementOwner == address(0)) revert SettlementRetrieveUnavailable();
308: if (settlementOwner == address(0)) revert SettlementRedeemUnavailable();
670: if (settlementReference.owner == address(0)) revert SettlementRetryUnavailable();
818: if (callee == address(0)) revert UnrecognizedBridgeAgent();
871: if (_hTokens.length == 0) revert SettlementRetryUnavailableUseCallout();
910: if (callee == address(0)) revert UnrecognizedBridgeAgent();
1145: if (_localAddress == address(0)) revert UnrecognizedLocalAddress();
1146: if (_underlyingAddress == address(0)) if (_deposit > 0) revert UnrecognizedUnderlyingAddress();
GitHub: 244, 282, 308, 670, 818, 871, 910, 1145, 1146
File: src/RootPort.sol
245: if (_globalAddress == address(0)) revert InvalidGlobalAddress();
246: if (_localAddress == address(0)) revert InvalidLocalAddress();
247: if (_underlyingAddress == address(0)) revert InvalidUnderlyingAddress();
264: if (_localAddress == address(0)) revert InvalidLocalAddress();
352: if (address(account) == address(0)) account = addVirtualAccount(_user);
360: if (_user == address(0)) revert InvalidUserAddress();
510: if (_coreRootRouter == address(0)) revert InvalidCoreRootRouter();
511: if (_coreRootBridgeAgent == address(0)) revert InvalidCoreRootBridgeAgent();
528: if (_coreBranchRouter == address(0)) revert InvalidCoreBranchRouter();
529: if (_coreBranchBridgeAgent == address(0)) revert InvalidCoreBrancBridgeAgent();
544: if (_coreBranchRouter == address(0)) revert InvalidCoreBranchRouter();
545: if (_coreBranchBridgeAgent == address(0)) revert InvalidCoreBrancBridgeAgent();
GitHub: 245, 246, 247, 264, 352, 360, 510, 511, 528, 529, 544, 545
If the old value is equal to the new value, not re-storing the value will avoid a Gsreset (2900 gas), potentially at the expense of a Gcoldsload (2100 gas) or a Gwarmaccess (100 gas)
There are 11 instances of this issue:
File: src/BranchPort.sol
331 function setCoreRouter(address _newCoreRouter) external override requiresCoreRouter {
332 require(coreBranchRouterAddress != address(0), "CoreRouter address is zero");
333 require(_newCoreRouter != address(0), "New CoreRouter address is zero");
334 coreBranchRouterAddress = _newCoreRouter;
335: }
362 function addStrategyToken(address _token, uint256 _minimumReservesRatio) external override requiresCoreRouter {
363 if (_minimumReservesRatio >= DIVISIONER || _minimumReservesRatio < MIN_RESERVE_RATIO) {
364 revert InvalidMinimumReservesRatio();
365 }
366
367 strategyTokens.push(_token);
368 getMinimumTokenReserveRatio[_token] = _minimumReservesRatio;
369 isStrategyToken[_token] = true;
370
371 emit StrategyTokenAdded(_token, _minimumReservesRatio);
372: }
382 function addPortStrategy(address _portStrategy, address _token, uint256 _dailyManagementLimit)
383 external
384 override
385 requiresCoreRouter
386 {
387 if (!isStrategyToken[_token]) revert UnrecognizedStrategyToken();
388 portStrategies.push(_portStrategy);
389 strategyDailyLimitAmount[_portStrategy][_token] = _dailyManagementLimit;
390 isPortStrategy[_portStrategy][_token] = true;
391
392 emit PortStrategyAdded(_portStrategy, _token, _dailyManagementLimit);
393: }
403 function updatePortStrategy(address _portStrategy, address _token, uint256 _dailyManagementLimit)
404 external
405 override
406 requiresCoreRouter
407 {
408 strategyDailyLimitAmount[_portStrategy][_token] = _dailyManagementLimit;
409
410 emit PortStrategyUpdated(_portStrategy, _token, _dailyManagementLimit);
411: }
414 function setCoreBranchRouter(address _coreBranchRouter, address _coreBranchBridgeAgent)
415 external
416 override
417 requiresCoreRouter
418 {
419 coreBranchRouterAddress = _coreBranchRouter;
420 isBridgeAgent[_coreBranchBridgeAgent] = true;
421 bridgeAgents.push(_coreBranchBridgeAgent);
422
423 emit CoreBranchSet(_coreBranchRouter, _coreBranchBridgeAgent);
424: }
GitHub: 331, 362, 382, 403, 414
File: src/RootPort.sol
239 function setAddresses(
240 address _globalAddress,
241 address _localAddress,
242 address _underlyingAddress,
243 uint256 _srcChainId
244 ) external override requiresCoreRootRouter {
245 if (_globalAddress == address(0)) revert InvalidGlobalAddress();
246 if (_localAddress == address(0)) revert InvalidLocalAddress();
247 if (_underlyingAddress == address(0)) revert InvalidUnderlyingAddress();
248
249 isGlobalAddress[_globalAddress] = true;
250 getGlobalTokenFromLocal[_localAddress][_srcChainId] = _globalAddress;
251 getLocalTokenFromGlobal[_globalAddress][_srcChainId] = _localAddress;
252 getLocalTokenFromUnderlying[_underlyingAddress][_srcChainId] = _localAddress;
253 getUnderlyingTokenFromLocal[_localAddress][_srcChainId] = _underlyingAddress;
254
255 emit LocalTokenAdded(_underlyingAddress, _localAddress, _globalAddress, _srcChainId);
256: }
259 function setLocalAddress(address _globalAddress, address _localAddress, uint256 _srcChainId)
260 external
261 override
262 requiresCoreRootRouter
263 {
264 if (_localAddress == address(0)) revert InvalidLocalAddress();
265
266 getGlobalTokenFromLocal[_localAddress][_srcChainId] = _globalAddress;
267 getLocalTokenFromGlobal[_globalAddress][_srcChainId] = _localAddress;
268
269 emit GlobalTokenAdded(_localAddress, _globalAddress, _srcChainId);
270: }
382 function addBridgeAgent(address _manager, address _bridgeAgent) external override requiresBridgeAgentFactory {
383 if (isBridgeAgent[_bridgeAgent]) revert AlreadyAddedBridgeAgent();
384
385 bridgeAgents.push(_bridgeAgent);
386 getBridgeAgentManager[_bridgeAgent] = _manager;
387 isBridgeAgent[_bridgeAgent] = true;
388
389 emit BridgeAgentAdded(_bridgeAgent, _manager);
390: }
438 function addNewChain(
439 address _coreBranchBridgeAgentAddress,
440 uint256 _chainId,
441 string memory _wrappedGasTokenName,
442 string memory _wrappedGasTokenSymbol,
443 uint8 _wrappedGasTokenDecimals,
444 address _newLocalBranchWrappedNativeTokenAddress,
445 address _newUnderlyingBranchWrappedNativeTokenAddress
446 ) external override onlyOwner {
447 // Check if chain already added
448 if (isChainId[_chainId]) revert AlreadyAddedChain();
449
450 // Create new global token for new chain's wrapped native token
451 address newGlobalToken = address(
452 IERC20hTokenRootFactory(ICoreRootRouter(coreRootRouterAddress).hTokenFactoryAddress()).createToken(
453 _wrappedGasTokenName, _wrappedGasTokenSymbol, _wrappedGasTokenDecimals
454 )
455 );
456
457 // Sync new branch bridge agent with root core bridge agent
458 IBridgeAgent(ICoreRootRouter(coreRootRouterAddress).bridgeAgentAddress()).syncBranchBridgeAgent(
459 _coreBranchBridgeAgentAddress, _chainId
460 );
461
462 // Update State
463
464 // 1. Add new chain to chainId mapping
465 isChainId[_chainId] = true;
466 // 2. Add new chain to global address mapping
467 isGlobalAddress[newGlobalToken] = true;
468 // 3. Add new branch local token to global token address mapping
469 getGlobalTokenFromLocal[_newLocalBranchWrappedNativeTokenAddress][_chainId] = newGlobalToken;
470 // 4. Add new global token to branch local token address mapping
471 getLocalTokenFromGlobal[newGlobalToken][_chainId] = _newLocalBranchWrappedNativeTokenAddress;
472 // 5. Add new branch underlying token to branch local token address mapping
473 getLocalTokenFromUnderlying[_newUnderlyingBranchWrappedNativeTokenAddress][_chainId] =
474 _newLocalBranchWrappedNativeTokenAddress;
475 // 6. Add new branch local token to branch underlying token address mapping
476 getUnderlyingTokenFromLocal[_newLocalBranchWrappedNativeTokenAddress][_chainId] =
477 _newUnderlyingBranchWrappedNativeTokenAddress;
478
479 emit NewChainAdded(_chainId);
480: }
483 function addEcosystemToken(address _ecoTokenGlobalAddress) external override onlyOwner {
484 // Check if token already added
485 if (isGlobalAddress[_ecoTokenGlobalAddress]) revert AlreadyAddedEcosystemToken();
486
487 // Check if token is already a underlying token in current chain
488 if (getUnderlyingTokenFromLocal[_ecoTokenGlobalAddress][localChainId] != address(0)) {
489 revert AlreadyAddedEcosystemToken();
490 }
491
492 // Check if token is already a local branch token in current chain
493 if (getLocalTokenFromUnderlying[_ecoTokenGlobalAddress][localChainId] != address(0)) {
494 revert AlreadyAddedEcosystemToken();
495 }
496
497 // Update State
498 // 1. Add new global token to global address mapping
499 isGlobalAddress[_ecoTokenGlobalAddress] = true;
500 // 2. Add new branch local token address to global token mapping
501 getGlobalTokenFromLocal[_ecoTokenGlobalAddress][localChainId] = _ecoTokenGlobalAddress;
502 // 3. Add new global token to branch local token address mapping
503 getLocalTokenFromGlobal[_ecoTokenGlobalAddress][localChainId] = _ecoTokenGlobalAddress;
504
505 emit EcosystemTokenAdded(_ecoTokenGlobalAddress);
506: }
509 function setCoreRootRouter(address _coreRootRouter, address _coreRootBridgeAgent) external override onlyOwner {
510 if (_coreRootRouter == address(0)) revert InvalidCoreRootRouter();
511 if (_coreRootBridgeAgent == address(0)) revert InvalidCoreRootBridgeAgent();
512
513 coreRootRouterAddress = _coreRootRouter;
514 coreRootBridgeAgentAddress = _coreRootBridgeAgent;
515 getBridgeAgentManager[_coreRootBridgeAgent] = owner();
516
517 emit CoreRootSet(_coreRootRouter, _coreRootBridgeAgent);
518: }
GitHub: 239, 259, 382, 438, 483, 509
The division cannot overflow, since both the numerator and the denominator are non-negative
There is one instance of this issue:
File: src/BranchPort.sol
473: return ((_currBalance + _strategyTokenDebt) * getMinimumTokenReserveRatio[_token]) / DIVISIONER;
GitHub: 473
External calls have an overhead of 100 gas, which can be avoided by not referencing the function using this
. Contracts are allowed to override their parents' functions and change the visibility from external
to public
, so make this change if it's required in order to call the function internally.
There are 2 instances of this issue:
File: src/BranchBridgeAgent.sol
579: address(this).excessivelySafeCall(
GitHub: 579
File: src/RootBridgeAgent.sol
424: (bool success,) = address(this).excessivelySafeCall(
GitHub: 424
If the arguments to the encode call can fit into the scratch space (two words or fewer), then it's more efficient to use assembly to generate the hash (80 gas):
keccak256(abi.encodePacked(x, y))
-> assembly {mstore(0x00, a); mstore(0x20, b); let hash := keccak256(0x00, 0x40); }
There is one instance of this issue:
File: src/RootPort.sol
362: newAccount = new VirtualAccount{salt: keccak256(abi.encode(_user))}(_user, address(this));
GitHub: 362
When a function with a memory
array is called externally, the abi.decode()
step has to copy read each index of the calldata
to memory
. Each copy costs at least 60 gas (i.e. 60 * <mem_array>.length
). Using calldata
directly, obviates the need for copies of words of the struct/array not being read. Note that even if an interface defines a function as having memory
arguments, it's still valid for implementation contracts to use calldata
arguments instead.
If the array is passed to an internal
function which passes the array to another internal function where the array is modified and therefore memory
is used in the external
call, it's still more gass-efficient to use calldata
when the external
function uses modifiers, since the modifiers may prevent the internal functions from being called. Structs have the same overhead as an array of length one
Note that I've also flagged instances where the function is public
but can be marked as external
since it's not called by the contract, and cases where a constructor is involved
There are 23 instances of this issue:
see instances
File: src/BranchBridgeAgent.sol
/// @audit callOutAndBridge(_dParams)
212: DepositInput memory _dParams,
/// @audit callOutAndBridgeMultiple(_dParams)
234: DepositMultipleInput memory _dParams,
/// @audit callOutSignedAndBridge(_dParams)
279: DepositInput memory _dParams,
/// @audit callOutSignedAndBridgeMultiple(_dParams)
309: DepositMultipleInput memory _dParams,
File: src/BranchPort.sol
/// @audit bridgeInMultiple(_amounts)
250: uint256[] memory _amounts,
/// @audit bridgeInMultiple(_deposits)
251: uint256[] memory _deposits
/// @audit bridgeOutMultiple(_amounts)
292: uint256[] memory _amounts,
/// @audit bridgeOutMultiple(_deposits)
293: uint256[] memory _deposits
File: src/RootBridgeAgent.sol
/// @audit bridgeIn(_dParams)
351: function bridgeIn(address _recipient, DepositParams memory _dParams, uint256 _srcChainId)
GitHub: 351
File: src/interfaces/IBranchBridgeAgent.sol
/// @audit callOutAndBridge(depositParams)
166: DepositInput memory depositParams,
/// @audit callOutAndBridgeMultiple(depositParams)
182: DepositMultipleInput memory depositParams,
/// @audit callOutSignedAndBridge(depositParams)
211: DepositInput memory depositParams,
/// @audit callOutSignedAndBridgeMultiple(depositParams)
230: DepositMultipleInput memory depositParams,
File: src/interfaces/IBranchPort.sol
/// @audit bridgeInMultiple(_amounts)
107: uint256[] memory _amounts,
/// @audit bridgeInMultiple(_deposits)
108: uint256[] memory _deposits
/// @audit bridgeOutMultiple(_amounts)
139: uint256[] memory _amounts,
/// @audit bridgeOutMultiple(_deposits)
140: uint256[] memory _deposits
File: src/interfaces/IMulticall2.sol
/// @audit aggregate(calls)
20: function aggregate(Call[] memory calls) external returns (uint256 blockNumber, bytes[] memory returnData);
GitHub: 20
File: src/interfaces/IRootBridgeAgent.sol
/// @audit bridgeIn(_dParams)
271: function bridgeIn(address _recipient, DepositParams memory _dParams, uint256 _srcChainId) external;
GitHub: 271
File: src/interfaces/IRootRouter.sol
/// @audit executeDepositSingle(dParams)
42: function executeDepositSingle(bytes memory params, DepositParams memory dParams, uint16 srcChainId)
/// @audit executeDepositMultiple(dParams)
53: function executeDepositMultiple(bytes memory params, DepositMultipleParams memory dParams, uint16 srcChainId)
/// @audit executeSignedDepositSingle(dParams)
74: DepositParams memory dParams,
/// @audit executeSignedDepositMultiple(dParams)
88: DepositMultipleParams memory dParams,
Skipping the external call when nothing will be transferred, will save at least 100 gas
There are 10 instances of this issue:
File: src/ArbitrumBranchPort.sol
66: _underlyingAddress.safeTransferFrom(_depositor, address(this), _deposit);
94: _underlyingAddress.safeTransfer(_recipient, _amount);
File: src/BaseBranchRouter.sol
167: _hToken.safeTransferFrom(msg.sender, address(this), _amount - _deposit);
GitHub: 167
File: src/BranchPort.sol
233: _underlyingAddress.safeTransfer(_recipient, _deposit);
GitHub: 233
File: src/RootBridgeAgent.sol
1151: _globalAddress.safeTransferFrom(_depositor, localPortAddress, _amount - _deposit);
GitHub: 1151
File: src/RootPort.sol
286: _hToken.safeTransfer(_recipient, _amount - _deposit);
301: _hToken.safeTransferFrom(_from, address(this), _amount);
311: _hToken.safeTransfer(_to, _amount);
File: src/VirtualAccount.sol
57: _token.safeTransfer(msg.sender, _amount);
62: ERC721(_token).transferFrom(address(this), msg.sender, _tokenId);
Even if you don't assign the call's second return value, it still gets copied to memory. Use assembly instead to prevent this and save 159 gas:
(bool success,) = payable(receiver).call{gas: gas, value: value}("");
-> bool success; assembly { success := call(gas, receiver, value, 0, 0, 0, 0) }
There are 9 instances of this issue:
File: src/ArbitrumBranchBridgeAgent.sol
103: _rootBridgeAgentAddress.call{value: msg.value}("");
GitHub: 103
File: src/BranchBridgeAgent.sol
717: (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata);
737: (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata);
File: src/RootBridgeAgent.sol
754: (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata);
779: (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata);
835: callee.call{value: msg.value}("");
927: callee.call{value: _value}("");
File: src/VirtualAccount.sol
74: if (isContract(_call.target)) (success, returnData[i]) = _call.target.call(_call.callData);
101: if (isContract(_call.target)) (success, returnData[i]) = _call.target.call{value: val}(_call.callData);
The issues below may be reported by other bots/wardens, but can be penalized/ignored since either the rule or the specified instances are invalid
The function being called may revert, which will be indicated by the return value to call()
/delegatecall()
. If the return value is not checked, the code will continue on as if there was no error, rather than reverting with the error encountered.
There are 9 instances of this issue:
File: src/MulticallRootRouter.sol
239: IVirtualAccount(userAccount).call(calls);
248: IVirtualAccount(userAccount).call(calls);
275: IVirtualAccount(userAccount).call(calls);
328: IVirtualAccount(userAccount).call(calls);
337: IVirtualAccount(userAccount).call(calls);
364: IVirtualAccount(userAccount).call(calls);
416: IVirtualAccount(userAccount).call(calls);
425: IVirtualAccount(userAccount).call(calls);
452: IVirtualAccount(userAccount).call(calls);
GitHub: 239, 248, 275, 328, 337, 364, 416, 425, 452
The general rule is valid, but the instances below are invalid
There is one instance of this issue:
File: src/BaseBranchRouter.sol
168: ERC20(_hToken).approve(_localPortAddress, _amount - _deposit);
GitHub: 168
When a type is downcast to a smaller type, the higher order bits are truncated, effectively applying a modulo to the original value. Without any other checks, this wrapping will lead to unexpected behavior and bugs
There are 5 instances of this issue:
File: src/BranchBridgeAgent.sol
/// @audit uint16
171: abi.encodePacked(uint16(2), _gasLimit, _remoteBranchExecutionGas, rootBridgeAgentAddress)
/// @audit uint16
776: abi.encodePacked(uint16(2), _gParams.gasLimit, _gParams.remoteBranchExecutionGas, rootBridgeAgentAddress)
File: src/RootBridgeAgent.sol
/// @audit uint16
151: abi.encodePacked(uint16(2), _gasLimit, _remoteBranchExecutionGas, getBranchBridgeAgent[_dstChainId])
/// @audit uint16
829: abi.encodePacked(uint16(2), _gParams.gasLimit, _gParams.remoteBranchExecutionGas, callee)
/// @audit uint16
921: abi.encodePacked(uint16(2), _gParams.gasLimit, _gParams.remoteBranchExecutionGas, callee)
Division by large numbers may result in the result being zero, due to solidity not supporting fractions. Consider requiring a minimum amount for the numerator to ensure that it is always larger than the denominator
There is one instance of this issue:
File: src/BranchPort.sol
490: lastManaged[msg.sender][_token] = (block.timestamp / 1 days) * 1 days;
GitHub: 490
The general rule is valid, but the instances below are invalid
There are 44 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/ArbitrumBranchPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/ArbitrumCoreBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BaseBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BranchBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BranchBridgeAgentExecutor.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/BranchPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/CoreBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/CoreRootRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/MulticallRootRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/MulticallRootRouterLibZip.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/RootBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/RootBridgeAgentExecutor.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/RootPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/VirtualAccount.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/BranchBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/ERC20hTokenBranchFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/ERC20hTokenRootFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/factories/RootBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/BridgeAgentConstants.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/BridgeAgentStructs.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IArbitrumBranchPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/interfaces/IBranchBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IBranchBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IBranchPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/interfaces/IBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/ICoreBranchRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IERC20hTokenBranch.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IERC20hTokenBranchFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IERC20hTokenRoot.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IERC20hTokenRootFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/ILayerZeroEndpoint.sol
3: pragma solidity >=0.5.0;
GitHub: 3
File: src/interfaces/ILayerZeroReceiver.sol
3: pragma solidity >=0.5.0;
GitHub: 3
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
3: pragma solidity >=0.5.0;
GitHub: 3
File: src/interfaces/IMulticall2.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IPortStrategy.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/interfaces/IRootBridgeAgent.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IRootBridgeAgentFactory.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IRootPort.sol
3: pragma solidity ^0.8.0;
GitHub: 3
File: src/interfaces/IRootRouter.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/interfaces/IVirtualAccount.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/token/ERC20hTokenBranch.sol
2: pragma solidity ^0.8.0;
GitHub: 2
File: src/token/ERC20hTokenRoot.sol
2: pragma solidity ^0.8.0;
GitHub: 2
The general rule is valid, but the instances below are invalid
There is one instance of this issue:
File: src/BaseBranchRouter.sol
168: ERC20(_hToken).approve(_localPortAddress, _amount - _deposit);
GitHub: 168
The general rule is valid, but the instances below are invalid
There are 27 instances of this issue:
File: src/BaseBranchRouter.sol
98 IBridgeAgent(localBridgeAgentAddress).callOutAndBridge{value: msg.value}(
99 payable(msg.sender), _params, _dParams, _gParams
100 );
101: }
113 IBridgeAgent(localBridgeAgentAddress).callOutAndBridgeMultiple{value: msg.value}(
114 payable(msg.sender), _params, _dParams, _gParams
115 );
116: }
File: src/BranchBridgeAgent.sol
717 (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata);
718
719 // No fallback is requested revert allowing for settlement retry.
720 if (!success) revert ExecutionFailure();
721: }
GitHub: 717
File: src/CoreBranchRouter.sol
54 IBridgeAgent(localBridgeAgentAddress).callOut{value: msg.value}(payable(msg.sender), payload, _gParams[0]);
55: }
78 IBridgeAgent(localBridgeAgentAddress).callOutSystem{value: msg.value}(payable(msg.sender), payload, _gParams);
79: }
184 IBridgeAgent(localBridgeAgentAddress).callOutSystem{value: msg.value}(payable(_refundee), payload, _gParams);
185: }
232 IBridgeAgent(localBridgeAgentAddress).callOutSystem{value: msg.value}(payable(_refundee), payload, _gParams);
233: }
File: src/CoreRootRouter.sol
139 IBridgeAgent(bridgeAgentAddress).callOut{value: msg.value}(
140 payable(_refundee), _refundee, _dstChainId, payload, _gParams[0]
141 );
142: }
174 IBridgeAgent(bridgeAgentAddress).callOut{value: msg.value}(
175 payable(_refundee), _refundee, _dstChainId, payload, _gParams
176 );
177: }
199 IBridgeAgent(bridgeAgentAddress).callOut{value: msg.value}(
200 payable(_refundee), _refundee, _dstChainId, payload, _gParams
201 );
202: }
226 IBridgeAgent(bridgeAgentAddress).callOut{value: msg.value}(
227 payable(_refundee), _refundee, _dstChainId, payload, _gParams
228 );
229: }
257 IBridgeAgent(bridgeAgentAddress).callOut{value: msg.value}(
258 payable(_refundee), _refundee, _dstChainId, payload, _gParams
259 );
260: }
287 IBridgeAgent(bridgeAgentAddress).callOut{value: msg.value}(
288 payable(_refundee), _refundee, _dstChainId, payload, _gParams
289 );
290: }
437 IBridgeAgent(bridgeAgentAddress).callOut{value: msg.value}(
438 payable(_refundee), _refundee, _dstChainId, payload, _gParams[0]
439 );
440: }
GitHub: 139, 174, 199, 226, 257, 287, 437
File: src/MulticallRootRouter.sol
275 IVirtualAccount(userAccount).call(calls);
276
277 // Withdraw assets from Virtual Account
278 for (uint256 i = 0; i < outputParams.outputTokens.length;) {
279 IVirtualAccount(userAccount).withdrawERC20(outputParams.outputTokens[i], outputParams.amountsOut[i]);
280:
248 IVirtualAccount(userAccount).call(calls);
249
250 // Withdraw assets from Virtual Account
251 IVirtualAccount(userAccount).withdrawERC20(outputParams.outputToken, outputParams.amountOut);
252
253: // Bridge Out assets
239 IVirtualAccount(userAccount).call(calls);
240
241 /// FUNC ID: 2 (multicallSingleOutput)
242 } else if (funcId == 0x02) {
243 // Decode Params
244: (Call[] memory calls, OutputParams memory outputParams, uint16 dstChainId, GasParams memory gasParams) =
364 IVirtualAccount(userAccount).call(calls);
365
366 // Withdraw assets from Virtual Account
367 for (uint256 i = 0; i < outputParams.outputTokens.length;) {
368 IVirtualAccount(userAccount).withdrawERC20(outputParams.outputTokens[i], outputParams.amountsOut[i]);
369:
337 IVirtualAccount(userAccount).call(calls);
338
339 // Withdraw assets from Virtual Account
340 IVirtualAccount(userAccount).withdrawERC20(outputParams.outputToken, outputParams.amountOut);
341
342: // Bridge Out assets
328 IVirtualAccount(userAccount).call(calls);
329
330 /// FUNC ID: 2 (multicallSingleOutput)
331 } else if (funcId == 0x02) {
332 // Decode Params
333: (Call[] memory calls, OutputParams memory outputParams, uint16 dstChainId, GasParams memory gasParams) =
452 IVirtualAccount(userAccount).call(calls);
453
454 // Withdraw assets from Virtual Account
455 for (uint256 i = 0; i < outputParams.outputTokens.length;) {
456 IVirtualAccount(userAccount).withdrawERC20(outputParams.outputTokens[i], outputParams.amountsOut[i]);
457:
425 IVirtualAccount(userAccount).call(calls);
426
427 // Withdraw assets from Virtual Account
428 IVirtualAccount(userAccount).withdrawERC20(outputParams.outputToken, outputParams.amountOut);
429
430: // Bridge Out assets
416 IVirtualAccount(userAccount).call(calls);
417
418 /// FUNC ID: 2 (multicallSingleOutput)
419 } else if (funcId == 0x02) {
420 // Decode Params
421: (Call[] memory calls, OutputParams memory outputParams, uint16 dstChainId, GasParams memory gasParams) =
524 IBridgeAgent(_bridgeAgentAddress).callOutAndBridge{value: msg.value}(
525 payable(refundee),
526 recipient,
527 dstChainId,
528 "",
529: SettlementInput(outputToken, amountOut, depositOut),
566 IBridgeAgent(_bridgeAgentAddress).callOutAndBridgeMultiple{value: msg.value}(
567 payable(refundee),
568 recipient,
569 dstChainId,
570 "",
571: SettlementMultipleInput(outputTokens, amountsOut, depositsOut),
GitHub: 275, 248, 239, 364, 337, 328, 452, 425, 416, 524, 566
File: src/VirtualAccount.sol
74 if (isContract(_call.target)) (success, returnData[i]) = _call.target.call(_call.callData);
75
76 if (!success) revert CallFailed();
77
78 unchecked {
79: ++i;
101 if (isContract(_call.target)) (success, returnData[i]) = _call.target.call{value: val}(_call.callData);
102
103 if (!success) revert CallFailed();
104
105 unchecked {
106: ++i;
[D‑08] Duplicated require()/revert() checks should be refactored to a modifier Or function to save gas
If the compiler inlines the function, there will be no gas savings. If it doesn't, there's extra runtime overhead due to the JUMP instructions. Either way, this suggestion is not helpful.
There are 12 instances of this issue:
see instances
File: src/BranchBridgeAgent.sol
441: if (deposit.owner != msg.sender) revert NotDepositOwner();
624: if (executionState[nonce] != STATUS_READY) revert AlreadyExecutedTransaction();
File: src/BranchPort.sol
560: if (!isStrategyToken[_token]) revert UnrecognizedStrategyToken();
GitHub: 560
File: src/CoreRootRouter.sol
366: revert();
GitHub: 366
File: src/MulticallRootRouter.sol
204: revert();
GitHub: 204
File: src/RootBridgeAgent.sol
670: if (settlementReference.owner == address(0)) revert SettlementRetryUnavailable();
910: if (callee == address(0)) revert UnrecognizedBridgeAgent();
File: src/RootPort.sol
264: if (_localAddress == address(0)) revert InvalidLocalAddress();
299: if (!isGlobalAddress[_hToken]) revert UnrecognizedToken();
544: if (_coreBranchRouter == address(0)) revert InvalidCoreBranchRouter();
545: if (_coreBranchBridgeAgent == address(0)) revert InvalidCoreBrancBridgeAgent();
File: src/VirtualAccount.sol
103: if (!success) revert CallFailed();
GitHub: 103
This instance appears only once
There are 56 instances of this issue:
see instances
File: src/ArbitrumBranchPort.sol
39: require(_rootPortAddress != address(0), "Root Port Address cannot be 0");
GitHub: 39
File: src/BaseBranchRouter.sol
61: require(_localBridgeAgentAddress != address(0), "Bridge Agent address cannot be 0");
213: require(_unlocked == 1);
File: src/BranchBridgeAgent.sol
125: require(_rootBridgeAgentAddress != address(0), "Root Bridge Agent Address cannot be the zero address.");
126 require(
127 _lzEndpointAddress != address(0) || _rootChainId == _localChainId,
128 "Layerzero Endpoint Address cannot be the zero address."
129: );
130: require(_localRouterAddress != address(0), "Local Router Address cannot be the zero address.");
131: require(_localPortAddress != address(0), "Local Port Address cannot be the zero address.");
923: require(_unlocked == 1);
GitHub: 125, 126, 130, 131, 923
File: src/BranchPort.sol
109: require(_owner != address(0), "Owner is zero address");
123: require(coreBranchRouterAddress == address(0), "Contract already initialized");
124: require(!isBridgeAgentFactory[_bridgeAgentFactory], "Contract already initialized");
126: require(_coreBranchRouter != address(0), "CoreBranchRouter is zero address");
127: require(_bridgeAgentFactory != address(0), "BridgeAgentFactory is zero address");
136: revert("Cannot renounce ownership");
181: require(ERC20(_token).balanceOf(address(this)) - currBalance == _amount, "Port Strategy Withdraw Failed");
213 require(
214 ERC20(_token).balanceOf(address(this)) - currBalance == amountToWithdraw, "Port Strategy Withdraw Failed"
215: );
332: require(coreBranchRouterAddress != address(0), "CoreRouter address is zero");
333: require(_newCoreRouter != address(0), "New CoreRouter address is zero");
567: require(_unlocked == 1);
GitHub: 109, 123, 124, 126, 127, 136, 181, 213, 332, 333, 567
File: src/CoreRootRouter.sol
84: require(_setup, "Contract is already initialized");
278: require(msg.sender == rootPortAddress, "Only root port can call");
File: src/MulticallRootRouter.sol
93: require(_localPortAddress != address(0), "Local Port Address cannot be 0");
94: require(_multicallAddress != address(0), "Multicall Address cannot be 0");
110: require(_bridgeAgentAddress != address(0), "Bridge Agent Address cannot be 0");
591: require(_unlocked == 1);
File: src/RootBridgeAgent.sol
111: require(_lzEndpointAddress != address(0), "Layerzero Enpoint Address cannot be zero address");
112: require(_localPortAddress != address(0), "Port Address cannot be zero address");
113: require(_localRouterAddress != address(0), "Router Address cannot be zero address");
1191: require(_unlocked == 1);
File: src/RootPort.sol
130: require(_bridgeAgentFactory != address(0), "Bridge Agent Factory cannot be 0 address.");
131: require(_coreRootRouter != address(0), "Core Root Router cannot be 0 address.");
132: require(_setup, "Setup ended.");
152: require(_coreRootBridgeAgent != address(0), "Core Root Bridge Agent cannot be 0 address.");
153: require(_coreLocalBranchBridgeAgent != address(0), "Core Local Branch Bridge Agent cannot be 0 address.");
154: require(_localBranchPortAddress != address(0), "Local Branch Port Address cannot be 0 address.");
155: require(isBridgeAgent[_coreRootBridgeAgent], "Core Bridge Agent doesn't exist.");
156: require(_setupCore, "Core Setup ended.");
167: revert("Cannot renounce ownership");
GitHub: 130, 131, 132, 152, 153, 154, 155, 156, 167
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
57: require(_coreRootBridgeAgent != address(0), "Core Root Bridge Agent Address cannot be 0");
84 require(
85 msg.sender == localCoreBranchRouterAddress, "Only the Core Branch Router can create a new Bridge Agent."
86: );
87 require(
88 _rootBridgeAgentFactoryAddress == rootBridgeAgentFactoryAddress,
89 "Root Bridge Agent Factory Address does not match."
90: );
File: src/factories/BranchBridgeAgentFactory.sol
61: require(_rootBridgeAgentFactoryAddress != address(0), "Root Bridge Agent Factory Address cannot be 0");
62 require(
63 _lzEndpointAddress != address(0) || _rootChainId == _localChainId,
64 "Layerzero Endpoint Address cannot be the zero address."
65: );
66: require(_localCoreBranchRouterAddress != address(0), "Core Branch Router Address cannot be 0");
67: require(_localPortAddress != address(0), "Port Address cannot be 0");
68: require(_owner != address(0), "Owner cannot be 0");
88: require(_coreRootBridgeAgent != address(0), "Core Root Bridge Agent cannot be 0");
120 require(
121 msg.sender == localCoreBranchRouterAddress, "Only the Core Branch Router can create a new Bridge Agent."
122: );
123 require(
124 _rootBridgeAgentFactoryAddress == rootBridgeAgentFactoryAddress,
125 "Root Bridge Agent Factory Address does not match."
126: );
GitHub: 61, 62, 66, 67, 68, 88, 120, 123
File: src/factories/ERC20hTokenBranchFactory.sol
43: require(_localPortAddress != address(0), "Port address cannot be 0");
61: require(_coreRouter != address(0), "CoreRouter address cannot be 0");
File: src/factories/ERC20hTokenRootFactory.sol
35: require(_rootPortAddress != address(0), "Root Port Address cannot be 0");
50: require(_coreRouter != address(0), "CoreRouter address cannot be 0");
File: src/factories/RootBridgeAgentFactory.sol
32: require(_rootPortAddress != address(0), "Root Port Address cannot be 0");
GitHub: 32
File: src/token/ERC20hTokenRoot.sol
39: require(_rootPortAddress != address(0), "Root Port Address cannot be 0");
40: require(_factoryAddress != address(0), "Factory Address cannot be 0");
It's already on the first line
There are 44 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/ArbitrumBranchPort.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/ArbitrumCoreBranchRouter.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/BaseBranchRouter.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/BranchBridgeAgent.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/BranchBridgeAgentExecutor.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/BranchPort.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/CoreBranchRouter.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/CoreRootRouter.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/MulticallRootRouter.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/MulticallRootRouterLibZip.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/RootBridgeAgent.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/RootBridgeAgentExecutor.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/RootPort.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/VirtualAccount.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/factories/BranchBridgeAgentFactory.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/factories/ERC20hTokenBranchFactory.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/factories/ERC20hTokenRootFactory.sol
1: // // SPDX-License-Identifier: MIT
GitHub: 1
File: src/factories/RootBridgeAgentFactory.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/BridgeAgentConstants.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/BridgeAgentStructs.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IArbitrumBranchPort.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IBranchBridgeAgent.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IBranchBridgeAgentFactory.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IBranchPort.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IBranchRouter.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/ICoreBranchRouter.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IERC20hTokenBranch.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IERC20hTokenBranchFactory.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IERC20hTokenRoot.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IERC20hTokenRootFactory.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/ILayerZeroEndpoint.sol
1: // SPDX-License-Identifier: BUSL-1.1
GitHub: 1
File: src/interfaces/ILayerZeroReceiver.sol
1: // SPDX-License-Identifier: BUSL-1.1
GitHub: 1
File: src/interfaces/ILayerZeroUserApplicationConfig.sol
1: // SPDX-License-Identifier: BUSL-1.1
GitHub: 1
File: src/interfaces/IMulticall2.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IPortStrategy.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IRootBridgeAgent.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IRootBridgeAgentFactory.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IRootPort.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IRootRouter.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/interfaces/IVirtualAccount.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/token/ERC20hTokenBranch.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
File: src/token/ERC20hTokenRoot.sol
1: // SPDX-License-Identifier: MIT
GitHub: 1
At least one bot is incorrectly flagging code comments as 'complicated arithmetic'
There are 18 instances of this issue:
see instances
File: src/ArbitrumCoreBranchRouter.sol
27: * -----------------------------
29: * -------------+---------------
File: src/CoreRootRouter.sol
29: * -----------------------------
31: * -------------+---------------
File: src/MulticallRootRouter.sol
46: * -----------------------------
48: * -------------+---------------
File: src/MulticallRootRouterLibZip.sol
15: * -----------------------------
17: * -------------+---------------
File: src/interfaces/IBranchBridgeAgent.sol
45: * ------------------------------
47: * -----+------------------------
68: * | callOut = 0x0 | 20b(recipient) + 4b(nonce) | ------------- | --- |
File: src/interfaces/ICoreBranchRouter.sol
16: * -----------------------------
18: * -------------+---------------
File: src/interfaces/IRootBridgeAgent.sol
43: * ------------------------------
45: * -----+------------------------
71: * | callOutSystem = 0x0 | 4b(nonce) | ------------- | --- |
72: * | callOut = 0x1 | 4b(nonce) | ------------- | --- |
75: * | callOutSigned = 0x4 | 20b(recip) + 4b(nonce) | ------------- | --- |
The examples below are not strings. Furthermore it's perfectly reasonable to use single quotes within text (p. 16).
There are 3 instances of this issue:
File: src/MulticallRootRouter.sol
499 /**
500: * @notice Function to call 'clearToken' on the Root Port.
523: //Move output hTokens from Root to Branch and call 'clearToken'.
565: //Move output hTokens from Root to Branch and call 'clearTokens'.
After Solidity version 0.6.9 both public
and external
functions save the same amount of gas, and since these files are >0.6.9, these findings are invalid
There are 6 instances of this issue:
File: src/BranchBridgeAgent.sol
578: function lzReceive(uint16, bytes calldata _srcAddress, uint64, bytes calldata _payload) public override {
587 function lzReceiveNonBlocking(address _endpoint, bytes calldata _srcAddress, bytes calldata _payload)
588 public
589 override
590: requiresEndpoint(_endpoint, _srcAddress)
File: src/RootBridgeAgent.sol
423: function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64, bytes calldata _payload) public {
434 function lzReceiveNonBlocking(
435 address _endpoint,
436 uint16 _srcChainId,
437 bytes calldata _srcAddress,
438 bytes calldata _payload
439: ) public override requiresEndpoint(_endpoint, _srcChainId, _srcAddress) {
File: src/VirtualAccount.sol
85: function payableCall(PayableCall[] calldata calls) public payable returns (bytes[] memory returnData) {
GitHub: 85
File: src/token/ERC20hTokenBranch.sol
35: function burn(uint256 amount) public override onlyOwner {
GitHub: 35
These are not revert()
calls, so these findings are invalid
There are 155 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
126: if (msg.sender != address(this)) revert LayerZeroUnauthorizedEndpoint();
127: if (_endpoint != rootBridgeAgentAddress) revert LayerZeroUnauthorizedEndpoint();
File: src/ArbitrumBranchPort.sol
63: if (_globalToken == address(0)) revert UnknownGlobalToken();
83: if (!IRootPort(_rootPortAddress).isGlobalToken(_globalAddress, localChainId)) revert UnknownGlobalToken();
90: if (_underlyingAddress == address(0)) revert UnknownUnderlyingToken();
File: src/ArbitrumCoreBranchRouter.sol
98: revert UnrecognizedBridgeAgentFactory();
108: revert UnrecognizedBridgeAgent();
169: revert UnrecognizedFunctionId();
File: src/BaseBranchRouter.sol
124: revert UnrecognizedFunctionId();
135: revert UnrecognizedFunctionId();
146: revert UnrecognizedFunctionId();
207: if (msg.sender != bridgeAgentExecutorAddress) revert UnrecognizedBridgeAgentExecutor();
File: src/BranchBridgeAgent.sol
354: if (deposit.owner != msg.sender) revert NotDepositOwner();
412: if (payload.length == 0) revert DepositRetryUnavailableUseCallout();
424: if (getDeposit[_depositNonce].owner != msg.sender) revert NotDepositOwner();
439: if (deposit.status == STATUS_SUCCESS) revert DepositRedeemUnavailable();
440: if (deposit.owner == address(0)) revert DepositRedeemUnavailable();
441: if (deposit.owner != msg.sender) revert NotDepositOwner();
696: revert UnknownFlag();
672: revert AlreadyExecutedTransaction();
646: if (executionState[nonce] != STATUS_READY) revert AlreadyExecutedTransaction();
624: if (executionState[nonce] != STATUS_READY) revert AlreadyExecutedTransaction();
604: if (executionState[nonce] != STATUS_READY) revert AlreadyExecutedTransaction();
720: if (!success) revert ExecutionFailure();
750: revert ExecutionFailure();
869: if (_hTokens.length > MAX_TOKENS_LENGTH) revert InvalidInput();
870: if (_hTokens.length != _tokens.length) revert InvalidInput();
871: if (_tokens.length != _amounts.length) revert InvalidInput();
872: if (_amounts.length != _deposits.length) revert InvalidInput();
938: if (msg.sender != address(this)) revert LayerZeroUnauthorizedEndpoint();
939: if (_endpoint != lzEndpointAddress) revert LayerZeroUnauthorizedEndpoint();
942: if (_srcAddress.length != 40) revert LayerZeroUnauthorizedCaller();
943: if (rootBridgeAgentAddress != address(uint160(bytes20(_srcAddress[20:])))) revert LayerZeroUnauthorizedCaller();
948: if (msg.sender != localRouterAddress) revert UnrecognizedRouter();
954: if (msg.sender != bridgeAgentExecutorAddress) revert UnrecognizedBridgeAgentExecutor();
GitHub: 354, 412, 424, 439, 440, 441, 696, 672, 646, 624, 604, 720, 750, 869, 870, 871, 872, 938, 939, 942, 943, 948, 954
File: src/BranchPort.sol
149: if (_amount > _excessReserves(_strategyTokenDebt, _token)) revert InsufficientReserves();
299: if (length > 255) revert InvalidInputArrays();
300: if (length != _underlyingAddresses.length) revert InvalidInputArrays();
301: if (_underlyingAddresses.length != _amounts.length) revert InvalidInputArrays();
302: if (_amounts.length != _deposits.length) revert InvalidInputArrays();
320: if (isBridgeAgent[_bridgeAgent]) revert AlreadyAddedBridgeAgent();
339: if (isBridgeAgentFactory[_newBridgeAgentFactory]) revert AlreadyAddedBridgeAgentFactory();
364: revert InvalidMinimumReservesRatio();
387: if (!isStrategyToken[_token]) revert UnrecognizedStrategyToken();
542: if (msg.sender != coreBranchRouterAddress) revert UnrecognizedCore();
548: if (!isBridgeAgent[msg.sender]) revert UnrecognizedBridgeAgent();
554: if (!isBridgeAgentFactory[msg.sender]) revert UnrecognizedBridgeAgentFactory();
560: if (!isStrategyToken[_token]) revert UnrecognizedStrategyToken();
561: if (!isPortStrategy[msg.sender][_token]) revert UnrecognizedPortStrategy();
GitHub: 149, 299, 300, 301, 302, 320, 339, 364, 387, 542, 548, 554, 560, 561
File: src/CoreBranchRouter.sol
147: revert UnrecognizedFunctionId();
212: revert UnrecognizedBridgeAgentFactory();
222: revert UnrecognizedBridgeAgent();
268: if (!IPort(_localPortAddress).isBridgeAgent(_branchBridgeAgent)) revert UnrecognizedBridgeAgent();
File: src/CoreRootRouter.sol
113: revert UnauthorizedCallerNotManager();
117: if (!IPort(rootPortAddress).isChainId(_dstChainId)) revert InvalidChainId();
120: if (IBridgeAgent(_rootBridgeAgent).getBranchBridgeAgent(_dstChainId) != address(0)) revert InvalidChainId();
123: if (!IBridgeAgent(_rootBridgeAgent).isBranchBridgeAgentAllowed(_dstChainId)) revert UnauthorizedChainId();
164: revert UnrecognizedBridgeAgentFactory();
327: revert UnrecognizedFunctionId();
345: revert UnrecognizedFunctionId();
412: if (_dstChainId == rootChainId) revert InvalidChainId();
415: revert UnrecognizedGlobalToken();
420: revert TokenAlreadyAdded();
461: if (IPort(rootPortAddress).isGlobalAddress(_underlyingAddress)) revert TokenAlreadyAdded();
462: if (IPort(rootPortAddress).isLocalToken(_underlyingAddress, _srcChainId)) revert TokenAlreadyAdded();
463: if (IPort(rootPortAddress).isUnderlyingToken(_underlyingAddress, _srcChainId)) revert TokenAlreadyAdded();
483: if (IPort(rootPortAddress).isLocalToken(_localAddress, _dstChainId)) revert TokenAlreadyAdded();
512: if (msg.sender != bridgeAgentExecutorAddress) revert UnrecognizedBridgeAgentExecutor();
GitHub: 113, 117, 120, 123, 164, 327, 345, 412, 415, 420, 461, 462, 463, 483, 512
File: src/MulticallRootRouter.sol
198: revert UnrecognizedFunctionId();
298: revert UnrecognizedFunctionId();
387: revert UnrecognizedFunctionId();
475: revert UnrecognizedFunctionId();
605: if (msg.sender != bridgeAgentExecutorAddress) revert UnrecognizedBridgeAgentExecutor();
GitHub: 198, 298, 387, 475, 605
File: src/RootBridgeAgent.sol
244: if (settlementReference.owner == address(0)) revert SettlementRetryUnavailable();
249: revert NotSettlementOwner();
282: if (settlementOwner == address(0)) revert SettlementRetrieveUnavailable();
287: revert NotSettlementOwner();
307: if (settlement.status == STATUS_SUCCESS) revert SettlementRedeemUnavailable();
308: if (settlementOwner == address(0)) revert SettlementRedeemUnavailable();
313: revert NotSettlementOwner();
357: if (_dParams.amount < _dParams.deposit) revert InvalidInputParams();
365: revert InvalidInputParams();
372: revert InvalidInputParams();
396: if (length > MAX_TOKENS_LENGTH) revert InvalidInputParams();
430: if (!success) if (msg.sender == getBranchBridgeAgent[localChainId]) revert ExecutionFailure();
733: revert UnknownFlag();
705: revert AlreadyExecutedTransaction();
670: if (settlementReference.owner == address(0)) revert SettlementRetryUnavailable();
675: revert NotSettlementOwner();
623: revert AlreadyExecutedTransaction();
583: revert AlreadyExecutedTransaction();
545: revert AlreadyExecutedTransaction();
519: revert AlreadyExecutedTransaction();
496: revert AlreadyExecutedTransaction();
473: revert AlreadyExecutedTransaction();
450: revert AlreadyExecutedTransaction();
757: if (!success) revert ExecutionFailure();
791: revert ExecutionFailure();
818: if (callee == address(0)) revert UnrecognizedBridgeAgent();
871: if (_hTokens.length == 0) revert SettlementRetryUnavailableUseCallout();
910: if (callee == address(0)) revert UnrecognizedBridgeAgent();
1057: if (_globalAddresses.length > MAX_TOKENS_LENGTH) revert InvalidInputParamsLength();
1060: if (_globalAddresses.length != _amounts.length) revert InvalidInputParamsLength();
1061: if (_amounts.length != _deposits.length) revert InvalidInputParamsLength();
1141: if (_amount == 0 && _deposit == 0) revert InvalidInputParams();
1142: if (_amount < _deposit) revert InvalidInputParams();
1145: if (_localAddress == address(0)) revert UnrecognizedLocalAddress();
1146: if (_underlyingAddress == address(0)) if (_deposit > 0) revert UnrecognizedUnderlyingAddress();
1159: revert InsufficientBalanceForSettlement();
1171: if (getBranchBridgeAgent[_branchChainId] != address(0)) revert AlreadyAddedBridgeAgent();
1199: if (msg.sender != localRouterAddress) revert UnrecognizedRouter();
1205: if (msg.sender != address(this)) revert LayerZeroUnauthorizedEndpoint();
1208: if (_endpoint != lzEndpointAddress) revert LayerZeroUnauthorizedEndpoint();
1210: if (_srcAddress.length != 40) revert LayerZeroUnauthorizedCaller();
1213: revert LayerZeroUnauthorizedCaller();
1221: if (msg.sender != bridgeAgentExecutorAddress) revert UnrecognizedExecutor();
1227: if (msg.sender != localPortAddress) revert UnrecognizedPort();
1234: revert UnrecognizedBridgeAgentManager();
GitHub: 244, 249, 282, 287, 307, 308, 313, 357, 365, 372, 396, 430, 733, 705, 670, 675, 623, 583, 545, 519, 496, 473, 450, 757, 791, 818, 871, 910, 1057, 1060, 1061, 1141, 1142, 1145, 1146, 1159, 1171, 1199, 1205, 1208, 1210, 1213, 1221, 1227, 1234
File: src/RootPort.sol
245: if (_globalAddress == address(0)) revert InvalidGlobalAddress();
246: if (_localAddress == address(0)) revert InvalidLocalAddress();
247: if (_underlyingAddress == address(0)) revert InvalidUnderlyingAddress();
264: if (_localAddress == address(0)) revert InvalidLocalAddress();
282: if (!isGlobalAddress[_hToken]) revert UnrecognizedToken();
290: if (_deposit > 0) if (!ERC20hTokenRoot(_hToken).mint(_recipient, _deposit, _srcChainId)) revert UnableToMint();
299: if (!isGlobalAddress[_hToken]) revert UnrecognizedToken();
309: if (!isGlobalAddress[_hToken]) revert UnrecognizedToken();
320: if (!isGlobalAddress[_hToken]) revert UnrecognizedToken();
330: if (!isGlobalAddress[_hToken]) revert UnrecognizedToken();
341: if (!isGlobalAddress[_hToken]) revert UnrecognizedToken();
342: if (!ERC20hTokenRoot(_hToken).mint(_to, _amount, localChainId)) revert UnableToMint();
360: if (_user == address(0)) revert InvalidUserAddress();
383: if (isBridgeAgent[_bridgeAgent]) revert AlreadyAddedBridgeAgent();
399: revert AlreadyAddedBridgeAgent();
402: revert BridgeAgentNotAllowed();
422: if (isBridgeAgentFactory[_bridgeAgentFactory]) revert AlreadyAddedBridgeAgentFactory();
448: if (isChainId[_chainId]) revert AlreadyAddedChain();
485: if (isGlobalAddress[_ecoTokenGlobalAddress]) revert AlreadyAddedEcosystemToken();
489: revert AlreadyAddedEcosystemToken();
494: revert AlreadyAddedEcosystemToken();
510: if (_coreRootRouter == address(0)) revert InvalidCoreRootRouter();
511: if (_coreRootBridgeAgent == address(0)) revert InvalidCoreRootBridgeAgent();
528: if (_coreBranchRouter == address(0)) revert InvalidCoreBranchRouter();
529: if (_coreBranchBridgeAgent == address(0)) revert InvalidCoreBrancBridgeAgent();
544: if (_coreBranchRouter == address(0)) revert InvalidCoreBranchRouter();
545: if (_coreBranchBridgeAgent == address(0)) revert InvalidCoreBrancBridgeAgent();
558: if (!isBridgeAgentFactory[msg.sender]) revert UnrecognizedBridgeAgentFactory();
564: if (!isBridgeAgent[msg.sender]) revert UnrecognizedBridgeAgent();
570: if (msg.sender != coreRootRouterAddress) revert UnrecognizedCoreRootRouter();
576: if (msg.sender != localBranchPortAddress) revert UnrecognizedLocalBranchPort();
GitHub: 245, 246, 247, 264, 282, 290, 299, 309, 320, 330, 341, 342, 360, 383, 399, 402, 422, 448, 485, 489, 494, 510, 511, 528, 529, 544, 545, 558, 564, 570, 576
File: src/VirtualAccount.sol
76: if (!success) revert CallFailed();
103: if (!success) revert CallFailed();
111: if (msg.value != valAccumulator) revert CallFailed();
163: revert UnauthorizedCaller();
File: src/factories/ERC20hTokenBranchFactory.sol
113: if (msg.sender != localCoreRouterAddress) revert UnrecognizedCoreRouter();
GitHub: 113
File: src/factories/ERC20hTokenRootFactory.sol
99: revert UnrecognizedCoreRouterOrPort();
GitHub: 99
safeTransferETH()
does not call functions on a contract and instead directly sends funds to the contract, so contract existence checks are not needed for these library calls.
There are 3 instances of this issue:
File: src/BranchBridgeAgentExecutor.sol
92: _recipient.safeTransferETH(address(this).balance);
126: _recipient.safeTransferETH(address(this).balance);
File: src/VirtualAccount.sol
52: msg.sender.safeTransferETH(_amount);
GitHub: 52
The compiler interprets ///
or /**
comments as this tag if one wasn't explicitly provided
There are 44 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
31 contract ArbitrumBranchBridgeAgent is BranchBridgeAgent {
32 /*///////////////////////////////////////////////////////////////
33 CONSTRUCTOR
34 //////////////////////////////////////////////////////////////*/
35
36 /**
37 * @notice Constructor for Arbitrum Branch Bridge Agent.
38 * @param _localChainId Local Chain Layer Zero Id.
39 * @param _rootBridgeAgentAddress Root Bridge Agent Address.
40 * @param _localRouterAddress Local Core Branch Router Address.
41 * @param _localPortAddress Local Branch Port Address.
42: */
GitHub: 31
File: src/ArbitrumBranchPort.sol
14: contract ArbitrumBranchPort is BranchPort, IArbitrumBranchPort {
GitHub: 14
File: src/ArbitrumCoreBranchRouter.sol
37 contract ArbitrumCoreBranchRouter is CoreBranchRouter {
38 /*///////////////////////////////////////////////////////////////
39 CONSTRUCTOR
40 //////////////////////////////////////////////////////////////*/
41 /**
42 * @notice Constructor for Arbitrum Core Branch Router.
43: */
GitHub: 37
File: src/BaseBranchRouter.sol
25: contract BaseBranchRouter is IBranchRouter, Ownable {
GitHub: 25
File: src/BranchBridgeAgent.sol
23: library DeployBranchBridgeAgent {
45: contract BranchBridgeAgent is IBranchBridgeAgent, BridgeAgentConstants {
File: src/BranchBridgeAgentExecutor.sol
15: library DeployBranchBridgeAgentExecutor {
29: contract BranchBridgeAgentExecutor is Ownable, BridgeAgentConstants {
File: src/BranchPort.sol
17: contract BranchPort is Ownable, IBranchPort {
GitHub: 17
File: src/CoreBranchRouter.sol
18 contract CoreBranchRouter is ICoreBranchRouter, BaseBranchRouter {
19: /// @notice hToken Factory Address.
GitHub: 18
File: src/CoreRootRouter.sol
38 contract CoreRootRouter is IRootRouter, Ownable {
39 /*///////////////////////////////////////////////////////////////
40 CORE ROOT ROUTER STATE
41 //////////////////////////////////////////////////////////////*/
42
43: /// @notice Boolean to indicate if the contract is in set up mode.
GitHub: 38
File: src/MulticallRootRouter.sol
57: contract MulticallRootRouter is IRootRouter, Ownable {
GitHub: 57
File: src/MulticallRootRouterLibZip.sol
26: contract MulticallRootRouterLibZip is MulticallRootRouter {
GitHub: 26
File: src/RootBridgeAgent.sol
32: contract RootBridgeAgent is IRootBridgeAgent, BridgeAgentConstants {
GitHub: 32
File: src/RootBridgeAgentExecutor.sol
13: library DeployRootBridgeAgentExecutor {
27 contract RootBridgeAgentExecutor is Ownable, BridgeAgentConstants {
28 /*///////////////////////////////////////////////////////////////
29 CONSTRUCTOR
30 //////////////////////////////////////////////////////////////*/
31 /**
32 * @notice Constructor for Root Bridge Agent Executor.
33 * @param _rootBridgeAgent the owner of the contract in charge of calling the different execution functions.
34: */
File: src/RootPort.sol
16: contract RootPort is Ownable, IRootPort {
GitHub: 16
File: src/VirtualAccount.sol
17: contract VirtualAccount is IVirtualAccount, ERC1155Receiver {
GitHub: 17
File: src/factories/ArbitrumBranchBridgeAgentFactory.sol
17 contract ArbitrumBranchBridgeAgentFactory is BranchBridgeAgentFactory {
18 /*///////////////////////////////////////////////////////////////
19 CONSTRUCTOR
20 //////////////////////////////////////////////////////////////*/
21
22 /**
23 * @notice Constructor for Bridge Agent Factory Contract.
24 * @param _rootChainId Root Chain Layer Zero Id.
25 * @param _rootBridgeAgentFactoryAddress Root Bridge Agent Factory Address.
26 * @param _localCoreBranchRouterAddress Local Core Branch Router Address.
27 * @param _localPortAddress Local Branch Port Address.
28 * @param _owner Owner of the contract.
29: */
GitHub: 17
File: src/factories/BranchBridgeAgentFactory.sol
19 contract BranchBridgeAgentFactory is Ownable, IBranchBridgeAgentFactory {
20: /// @notice Local Chain Id.
GitHub: 19
File: src/factories/ERC20hTokenBranchFactory.sol
12 contract ERC20hTokenBranchFactory is Ownable, IERC20hTokenBranchFactory {
13: /// @notice Local Network Identifier.
GitHub: 12
File: src/factories/ERC20hTokenRootFactory.sol
12 contract ERC20hTokenRootFactory is Ownable, IERC20hTokenRootFactory {
13: /// @notice Local Network Identifier.
GitHub: 12
File: src/factories/RootBridgeAgentFactory.sol
11 contract RootBridgeAgentFactory is IRootBridgeAgentFactory {
12: /// @notice Root Chain Id
GitHub: 11
File: src/interfaces/BridgeAgentConstants.sol
10 contract BridgeAgentConstants {
11 // Settlement / Deposit Execution Status
12:
GitHub: 10
File: src/interfaces/IArbitrumBranchPort.sol
16 interface IArbitrumBranchPort is IBranchPort {
17 /*///////////////////////////////////////////////////////////////
18 EXTERNAL FUNCTIONS
19 //////////////////////////////////////////////////////////////*/
20
21 /**
22 * @notice Function to deposit underlying/native token amount into Port in exchange for Local hToken.
23 * @param _depositor underlying/native token depositor.
24 * @param _recipient hToken receiver.
25 * @param _underlyingAddress underlying/native token address.
26 * @param _amount amount of tokens.
27: */
GitHub: 16
File: src/interfaces/IBranchBridgeAgent.sol
87 interface IBranchBridgeAgent is ILayerZeroReceiver {
88 /*///////////////////////////////////////////////////////////////
89 VIEW FUNCTIONS
90 //////////////////////////////////////////////////////////////*/
91
92 /**
93 * @notice External function to return the Branch Chain's Local Port Address.
94 * @return address of the Branch Chain's Local Port.
95: */
GitHub: 87
File: src/interfaces/IBranchBridgeAgentFactory.sol
12 interface IBranchBridgeAgentFactory {
13 /*///////////////////////////////////////////////////////////////
14 BRIDGE AGENT FUNCTIONS
15 //////////////////////////////////////////////////////////////*/
16
17 /**
18 * @notice Creates a new Branch Bridge Agent.
19 * @param newRootRouterAddress New Root Router Address.
20 * @param rootBridgeAgentAddress Root Bridge Agent Address.
21 * @param _rootBridgeAgentFactoryAddress Root Bridge Agent Factory Address.
22 * @return newBridgeAgent New Bridge Agent Address.
23: */
GitHub: 12
File: src/interfaces/IBranchPort.sol
14 interface IBranchPort {
15 /*///////////////////////////////////////////////////////////////
16 VIEW FUNCTIONS
17 //////////////////////////////////////////////////////////////*/
18 /**
19 * @notice Returns true if the address is a Bridge Agent.
20 * @param _bridgeAgent Bridge Agent address.
21 * @return bool.
22: */
GitHub: 14
File: src/interfaces/IBranchRouter.sol
21 interface IBranchRouter {
22 /*///////////////////////////////////////////////////////////////
23 VIEW / STATE
24 //////////////////////////////////////////////////////////////*/
25
26: /// @notice External function to return the Branch Chain's Local Port Address.
GitHub: 21
File: src/interfaces/ICoreBranchRouter.sol
27 interface ICoreBranchRouter {
28 /*///////////////////////////////////////////////////////////////
29 EXTERNAL FUNCTIONS
30 //////////////////////////////////////////////////////////////*/
31
32 /**
33 * @notice Function to deploy/add a token already present in the global environment to a branch chain.
34 * @param _globalAddress the address of the global virtualized token.
35 * @param _dstChainId the chain to which the token will be added.
36 * @param _gasParams Gas parameters for remote execution.
37: */
GitHub: 27
File: src/interfaces/IERC20hTokenBranch.sol
11 interface IERC20hTokenBranch {
12 /*///////////////////////////////////////////////////////////////
13 ERC20 LOGIC
14 //////////////////////////////////////////////////////////////*/
15
16 /**
17 * @notice Function to mint tokens in the Branch Chain.
18 * @param account Address of the account to receive the tokens.
19 * @param amount Amount of tokens to be minted.
20 * @return Boolean indicating if the operation was successful.
21: */
GitHub: 11
File: src/interfaces/IERC20hTokenBranchFactory.sol
13 interface IERC20hTokenBranchFactory {
14 /*///////////////////////////////////////////////////////////////
15 hTOKEN FUNCTIONS
16 //////////////////////////////////////////////////////////////*/
17 /**
18 * @notice Function to create a new Branch hToken.
19 * @param _name Name of the Token.
20 * @param _symbol Symbol of the Token.
21 * @param _decimals Decimals of the Token.
22 * @param _addPrefix Boolean to add or not the chain prefix to the token name and symbol.
23: */
GitHub: 13
File: src/interfaces/IERC20hTokenRoot.sol
12 interface IERC20hTokenRoot {
13 /*///////////////////////////////////////////////////////////////
14 VIEW FUNCTIONS
15 //////////////////////////////////////////////////////////////*/
16
17 /// @notice View Function returns Local Network Identifier.
18: /// @return Local Network Identifier.
GitHub: 12
File: src/interfaces/IERC20hTokenRootFactory.sol
13 interface IERC20hTokenRootFactory {
14 /*///////////////////////////////////////////////////////////////
15 hTOKEN FUNCTIONS
16 //////////////////////////////////////////////////////////////*/
17
18 /**
19 * @notice Function to create a new hToken.
20 * @param _name Name of the Token.
21 * @param _symbol Symbol of the Token.
22 * @param _decimals Decimals of the Token.
23: */
GitHub: 13
File: src/interfaces/IMulticall2.sol
9: interface IMulticall2 {
GitHub: 9
File: src/interfaces/IPortStrategy.sol
12 interface IPortStrategy {
13 /*///////////////////////////////////////////////////////////////
14 TOKEN MANAGEMENT
15 //////////////////////////////////////////////////////////////*/
16
17 /**
18 * @notice Function to withdraw underlying/native token amount back into Branch Port.
19 * @param _recipient hToken receiver.
20 * @param _token native token address.
21 * @param _amount amount of tokens.
22: */
GitHub: 12
File: src/interfaces/IRootBridgeAgent.sol
94 interface IRootBridgeAgent is ILayerZeroReceiver {
95 /*///////////////////////////////////////////////////////////////
96 VIEW FUNCTIONS
97 //////////////////////////////////////////////////////////////*/
98
99 /**
100 * @notice Function that returns the current settlement nonce.
101 * @return nonce bridge agent's current settlement nonce
102 *
103: */
GitHub: 94
File: src/interfaces/IRootBridgeAgentFactory.sol
11 interface IRootBridgeAgentFactory {
12 /*///////////////////////////////////////////////////////////////
13 BRIDGE AGENT FUNCTIONS
14 //////////////////////////////////////////////////////////////*/
15:
GitHub: 11
File: src/interfaces/IRootPort.sol
10: interface ICoreRootRouter {
31 interface IRootPort {
32 /*///////////////////////////////////////////////////////////////
33 VIEW FUNCTIONS
34 //////////////////////////////////////////////////////////////*/
35 /**
36 * @notice View Function returns True if the chain Id has been added to the system.
37 * @param _chainId The Layer Zero chainId of the chain.
38 * @return bool True if the chain Id has been added to the system.
39: */
File: src/interfaces/IRootRouter.sol
14 interface IRootRouter {
15 /*///////////////////////////////////////////////////////////////
16 LAYERZERO FUNCTIONS
17 ///////////////////////////////////////////////////////////////*/
18
19 /**
20 * @notice Function to execute Branch Bridge Agent system initiated requests with no asset deposit.
21 * @param params data received from messaging layer.
22 * @param srcChainId chain where the request originated from.
23 *
24: */
GitHub: 14
File: src/interfaces/IVirtualAccount.sol
27 interface IVirtualAccount is IERC721Receiver {
28 /**
29 * @notice Returns the address of the user that owns the VirtualAccount.
30 * @return The address of the user that owns the VirtualAccount.
31: */
GitHub: 27
File: src/token/ERC20hTokenBranch.sol
12: contract ERC20hTokenBranch is ERC20, Ownable, IERC20hTokenBranch {
GitHub: 12
File: src/token/ERC20hTokenRoot.sol
12 contract ERC20hTokenRoot is ERC20, Ownable, IERC20hTokenRoot {
13: /// @inheritdoc IERC20hTokenRoot
GitHub: 12
The instances below are already CamelCase (events are supposed to use CamelCase, not lowerCamelCase)
There are 28 instances of this issue:
File: src/interfaces/IBranchBridgeAgent.sol
332: event LogExecute(uint256 indexed nonce);
333: event LogFallback(uint256 indexed nonce);
File: src/interfaces/IBranchPort.sol
220: event DebtCreated(address indexed _strategy, address indexed _token, uint256 _amount);
221: event DebtRepaid(address indexed _strategy, address indexed _token, uint256 _amount);
223: event StrategyTokenAdded(address indexed _token, uint256 indexed _minimumReservesRatio);
224: event StrategyTokenToggled(address indexed _token);
226 event PortStrategyAdded(
227 address indexed _portStrategy, address indexed _token, uint256 indexed _dailyManagementLimit
228: );
229: event PortStrategyToggled(address indexed _portStrategy, address indexed _token);
230 event PortStrategyUpdated(
231 address indexed _portStrategy, address indexed _token, uint256 indexed _dailyManagementLimit
232: );
234: event BridgeAgentFactoryAdded(address indexed _bridgeAgentFactory);
235: event BridgeAgentFactoryToggled(address indexed _bridgeAgentFactory);
237: event BridgeAgentToggled(address indexed _bridgeAgent);
239: event CoreBranchSet(address indexed _coreBranchRouter, address indexed _coreBranchBridgeAgent);
GitHub: 220, 221, 223, 224, 226, 229, 230, 234, 235, 237, 239
File: src/interfaces/IRootBridgeAgent.sol
337: event LogExecute(uint256 indexed depositNonce, uint256 indexed srcChainId);
338: event LogFallback(uint256 indexed settlementNonce, uint256 indexed dstChainId);
File: src/interfaces/IRootPort.sol
371: event BridgeAgentFactoryAdded(address indexed bridgeAgentFactory);
372: event BridgeAgentFactoryToggled(address indexed bridgeAgentFactory);
374: event BridgeAgentAdded(address indexed bridgeAgent, address indexed manager);
375: event BridgeAgentToggled(address indexed bridgeAgent);
376: event BridgeAgentSynced(address indexed bridgeAgent, address indexed rootBridgeAgent, uint256 indexed srcChainId);
378: event NewChainAdded(uint256 indexed chainId);
380: event VirtualAccountCreated(address indexed user, address account);
382 event LocalTokenAdded(
383 address indexed underlyingAddress, address indexed localAddress, address indexed globalAddress, uint256 chainId
384: );
385: event GlobalTokenAdded(address indexed localAddress, address indexed globalAddress, uint256 indexed chainId);
386: event EcosystemTokenAdded(address indexed ecoTokenGlobalAddress);
387: event CoreRootSet(address indexed coreRootRouter, address indexed coreRootBridgeAgent);
388 event CoreBranchSet(
389 address indexed coreBranchRouter, address indexed coreBranchBridgeAgent, uint16 indexed dstChainId
390: );
391 event CoreBranchSynced(
392 address indexed coreBranchRouter, address indexed coreBranchBridgeAgent, uint16 indexed dstChainId
393: );
GitHub: 371, 372, 374, 375, 376, 378, 380, 382, 385, 386, 387, 388, 391
There are 3 instances of this issue:
File: src/BranchBridgeAgent.sol
127: _lzEndpointAddress != address(0) || _rootChainId == _localChainId,
GitHub: 127
File: src/BranchPort.sol
363: if (_minimumReservesRatio >= DIVISIONER || _minimumReservesRatio < MIN_RESERVE_RATIO) {
GitHub: 363
File: src/factories/BranchBridgeAgentFactory.sol
63: _lzEndpointAddress != address(0) || _rootChainId == _localChainId,
GitHub: 63
The compiler interprets ///
or /**
comments as this tag if one wasn't explicitly provided
There are 305 instances of this issue:
see instances
File: src/ArbitrumBranchBridgeAgent.sol
43 constructor(
44 uint16 _localChainId,
45 address _rootBridgeAgentAddress,
46 address _localRouterAddress,
47 address _localPortAddress
48 )
49 BranchBridgeAgent(
50 _localChainId,
51 _localChainId,
52 _rootBridgeAgentAddress,
53 address(0),
54 _localRouterAddress,
55 _localPortAddress
56 )
57: {}
69: function depositToPort(address underlyingAddress, uint256 amount) external payable lock {
79: function withdrawFromPort(address localAddress, uint256 amount) external payable lock {
89: function retrySettlement(uint32, bytes calldata, GasParams[2] calldata, bool) external payable override lock {}
File: src/ArbitrumBranchPort.sol
38: constructor(uint16 _localChainId, address _rootPortAddress, address _owner) BranchPort(_owner) {
50 function depositToPort(address _depositor, address _recipient, address _underlyingAddress, uint256 _deposit)
51 external
52 override
53 lock
54 requiresBridgeAgent
55: {
73 function withdrawFromPort(address _depositor, address _recipient, address _globalAddress, uint256 _amount)
74 external
75 override
76 lock
77 requiresBridgeAgent
78: {
File: src/ArbitrumCoreBranchRouter.sol
44: constructor() CoreBranchRouter
For transparency, the sponsor has provided their input on the Medium findings for this bot report. Their response is below: