diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 25ab6b3886..bd65c55089 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -67,7 +67,7 @@ jobs: run: yarn test test-contracts: - name: Test storage layout and signatures + name: Test storage layout, signatures and look for unused errors runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -98,6 +98,12 @@ jobs: - name: Test function signatures run: yarn run test:signatures + - name: Run unused Solidity errors checker + uses: OffchainLabs/actions/check-unused-errors@main + with: + directory: './contracts' + exceptions_file: './test/unused-errors/exceptions.txt' + test-e2e: name: Test e2e runs-on: ubuntu-latest @@ -112,7 +118,6 @@ jobs: no-token-bridge: true no-l3-token-bridge: true token-bridge-branch: '${{ github.head_ref }}' - nitro-testnode-ref: node-18 - name: Setup node/yarn uses: actions/setup-node@v3 @@ -136,6 +141,9 @@ jobs: - name: Verify creation code generation run: yarn test:creation-code + - name: Test e2e orbit token bridge actions + run: yarn hardhat test test-e2e/orbitTokenBridge.ts + test-e2e-custom-fee-token: name: Test e2e on custom fee token chain runs-on: ubuntu-latest @@ -151,7 +159,6 @@ jobs: no-token-bridge: true no-l3-token-bridge: true token-bridge-branch: '${{ github.head_ref }}' - nitro-testnode-ref: node-18 - name: Setup node/yarn uses: actions/setup-node@v3 @@ -194,7 +201,6 @@ jobs: no-l3-token-bridge: true token-bridge-branch: '${{ github.head_ref }}' nitro-contracts-branch: 'develop' - nitro-testnode-ref: 'non18-decimal-token-node-18' - name: Setup node/yarn uses: actions/setup-node@v3 diff --git a/.gitignore b/.gitignore index 6b590d4029..359ea6a55c 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,7 @@ network.json # Gambit (mutation test) files gambit_out/ -test-mutation/mutant_test_env/ \ No newline at end of file +test-mutation/mutant_test_env/ + +# bridged usdc deployment script +registerUsdcGatewayTx.json \ No newline at end of file diff --git a/contracts/tokenbridge/arbitrum/IArbToken.sol b/contracts/tokenbridge/arbitrum/IArbToken.sol index b38ca8b376..192b2f9a10 100644 --- a/contracts/tokenbridge/arbitrum/IArbToken.sol +++ b/contracts/tokenbridge/arbitrum/IArbToken.sol @@ -19,6 +19,8 @@ /** * @title Minimum expected interface for L2 token that interacts with the L2 token bridge (this is the interface necessary * for a custom token that interacts with the bridge, see TestArbCustomToken.sol for an example implementation). + * @dev For the token to be compatible out of the box with the tooling available (e.g., the Arbitrum bridge), it is + * recommended to keep the implementation of this interface as close as possible to the `TestArbCustomToken` example. */ // solhint-disable-next-line compiler-version diff --git a/contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol b/contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol index 30487e4aa1..c15ecba0f6 100644 --- a/contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol +++ b/contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol @@ -137,7 +137,7 @@ abstract contract L2ArbitrumGateway is L2ArbitrumMessenger, TokenGateway { uint256, /* _maxGas */ uint256, /* _gasPriceBid */ bytes calldata _data - ) public payable override returns (bytes memory res) { + ) public payable virtual override returns (bytes memory res) { // This function is set as public and virtual so that subclasses can override // it and add custom validation for callers (ie only whitelisted users) @@ -163,7 +163,7 @@ abstract contract L2ArbitrumGateway is L2ArbitrumMessenger, TokenGateway { { address l2Token = calculateL2TokenAddress(_l1Token); require(l2Token.isContract(), "TOKEN_NOT_DEPLOYED"); - require(IArbToken(l2Token).l1Address() == _l1Token, "NOT_EXPECTED_L1_TOKEN"); + require(_isValidTokenAddress(_l1Token, l2Token), "NOT_EXPECTED_L1_TOKEN"); _amount = outboundEscrowTransfer(l2Token, _from, _amount); id = triggerWithdrawal(_l1Token, _from, _to, _amount, _extraData); @@ -252,33 +252,14 @@ abstract contract L2ArbitrumGateway is L2ArbitrumMessenger, TokenGateway { ); if (shouldHalt) return; } - // ignores gatewayData if token already deployed - { - // validate if L1 address supplied matches that of the expected L2 address - (bool success, bytes memory _l1AddressData) = expectedAddress.staticcall( - abi.encodeWithSelector(IArbToken.l1Address.selector) - ); - - bool shouldWithdraw; - if (!success || _l1AddressData.length < 32) { - shouldWithdraw = true; - } else { - // we do this in the else branch since we want to avoid reverts - // and `toAddress` reverts if _l1AddressData has a short length - // `_l1AddressData` should be 12 bytes of padding then 20 bytes for the address - address expectedL1Address = BytesLib.toAddress(_l1AddressData, 12); - if (expectedL1Address != _token) { - shouldWithdraw = true; - } - } - - if (shouldWithdraw) { - // we don't need the return value from triggerWithdrawal since this is forcing - // a withdrawal back to the L1 instead of composing with a L2 dapp - triggerWithdrawal(_token, address(this), _from, _amount, ""); - return; - } + // validate if L1 address supplied matches that of the expected L2 address + bool shouldWithdraw = !_isValidTokenAddress(_token, expectedAddress); + if (shouldWithdraw) { + // we don't need the return value from triggerWithdrawal since this is forcing + // a withdrawal back to the L1 instead of composing with a L2 dapp + triggerWithdrawal(_token, address(this), _from, _amount, ""); + return; } inboundEscrowTransfer(expectedAddress, _to, _amount); @@ -296,4 +277,34 @@ abstract contract L2ArbitrumGateway is L2ArbitrumMessenger, TokenGateway { uint256 _amount, bytes memory gatewayData ) internal virtual returns (bool shouldHalt); -} + + /** + * @notice Check if expected token address matches the provided one + * @param _l1Address provided address of L1 token + * @param _expectedL2Address address of L2 gateway expects + * @return true if addresses match, false otherwise + */ + function _isValidTokenAddress(address _l1Address, address _expectedL2Address) + internal + view + virtual + returns (bool) + { + (bool success, bytes memory _l1AddressData) = + _expectedL2Address.staticcall(abi.encodeWithSelector(IArbToken.l1Address.selector)); + + if (!success || _l1AddressData.length < 32) { + return false; + } else { + // we do this in the else branch since we want to avoid reverts + // and `toAddress` reverts if _l1AddressData has a short length + // `_l1AddressData` should be 12 bytes of padding then 20 bytes for the address + address expectedL1Address = BytesLib.toAddress(_l1AddressData, 12); + if (expectedL1Address != _l1Address) { + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol b/contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol new file mode 100644 index 0000000000..4577940c3b --- /dev/null +++ b/contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.4; + +import "./L2ArbitrumGateway.sol"; +import {IFiatToken, IFiatTokenProxy} from "../../ethereum/gateway/L1USDCGateway.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +/** + * @title Child chain custom gateway for USDC implementing Bridged USDC Standard. + * @notice Reference to the Circle's Bridged USDC Standard: + * https://github.com/circlefin/stablecoin-evm/blob/master/doc/bridged_USDC_standard.md + * + * @dev This contract can be used on new Orbit chains which want to provide USDC + * bridging solution and keep the possibility to upgrade to native USDC at + * some point later. This solution will NOT be used in existing Arbitrum chains. + * + * Parent chain custom gateway to be used along this child chain custom gateway is + * L1USDCGateway (when eth is used to pay fees) or L1OrbitUSDCGateway (when custom fee token is used). + * This custom gateway differs from standard gateway in the following ways: + * - it supports a single parent chain - child chain USDC token pair + * - it is ownable + * - withdrawals can be paused by the owner + * - owner can set an "transferrer" account which will be able to transfer USDC ownership + * - transferrer can transfer USDC owner and proxyAdmin + * + * NOTE: before withdrawing funds, make sure that recipient address is not blacklisted on the parent chain. + * Also, make sure that USDC token itself is not paused. Otherwise funds might get stuck. + */ +contract L2USDCGateway is L2ArbitrumGateway { + using SafeERC20 for IERC20; + using Address for address; + + address public l1USDC; + address public l2USDC; + address public owner; + address public usdcOwnershipTransferrer; + bool public withdrawalsPaused; + + event WithdrawalsPaused(); + event WithdrawalsUnpaused(); + event OwnerSet(address indexed owner); + event USDCOwnershipTransferrerSet(address indexed usdcOwnershipTransferrer); + event USDCOwnershipTransferred(address indexed newOwner, address indexed newProxyAdmin); + + error L2USDCGateway_WithdrawalsAlreadyPaused(); + error L2USDCGateway_WithdrawalsAlreadyUnpaused(); + error L2USDCGateway_WithdrawalsPaused(); + error L2USDCGateway_InvalidL1USDC(); + error L2USDCGateway_InvalidL2USDC(); + error L2USDCGateway_NotOwner(); + error L2USDCGateway_InvalidOwner(); + error L2USDCGateway_NotUSDCOwnershipTransferrer(); + + modifier onlyOwner() { + if (msg.sender != owner) { + revert L2USDCGateway_NotOwner(); + } + _; + } + + function initialize( + address _l1Counterpart, + address _router, + address _l1USDC, + address _l2USDC, + address _owner + ) public { + if (_l1USDC == address(0)) { + revert L2USDCGateway_InvalidL1USDC(); + } + if (_l2USDC == address(0)) { + revert L2USDCGateway_InvalidL2USDC(); + } + if (_owner == address(0)) { + revert L2USDCGateway_InvalidOwner(); + } + L2ArbitrumGateway._initialize(_l1Counterpart, _router); + l1USDC = _l1USDC; + l2USDC = _l2USDC; + owner = _owner; + } + + /** + * @notice Pause all withdrawals. This can only be called by the owner. + */ + function pauseWithdrawals() external onlyOwner { + if (withdrawalsPaused) { + revert L2USDCGateway_WithdrawalsAlreadyPaused(); + } + withdrawalsPaused = true; + emit WithdrawalsPaused(); + } + + /** + * @notice Unpause withdrawals. This can only be called by the owner. + */ + function unpauseWithdrawals() external onlyOwner { + if (!withdrawalsPaused) { + revert L2USDCGateway_WithdrawalsAlreadyUnpaused(); + } + withdrawalsPaused = false; + emit WithdrawalsUnpaused(); + } + + /** + * @notice Sets a new owner. + */ + function setOwner(address newOwner) external onlyOwner { + if (newOwner == address(0)) { + revert L2USDCGateway_InvalidOwner(); + } + owner = newOwner; + emit OwnerSet(newOwner); + } + + /** + * @notice Sets the account which is able to transfer USDC role away from the gateway to some other account. + */ + function setUsdcOwnershipTransferrer(address _usdcOwnershipTransferrer) external onlyOwner { + usdcOwnershipTransferrer = _usdcOwnershipTransferrer; + emit USDCOwnershipTransferrerSet(_usdcOwnershipTransferrer); + } + + /** + * @notice In accordance with bridged USDC standard, the ownership of the USDC token contract is transferred + * to the new owner, and the proxy admin is transferred to the caller (usdcOwnershipTransferrer). + * @dev For transfer to be successful, this gateway should be both the owner and the proxy admin of L2 USDC token. + */ + function transferUSDCRoles(address _owner) external { + if (msg.sender != usdcOwnershipTransferrer) { + revert L2USDCGateway_NotUSDCOwnershipTransferrer(); + } + + IFiatTokenProxy(l2USDC).changeAdmin(msg.sender); + IFiatToken(l2USDC).transferOwnership(_owner); + + emit USDCOwnershipTransferred(_owner, msg.sender); + } + + /** + * @notice Entrypoint for withdrawing USDC, can be used only if withdrawals are not paused. + */ + function outboundTransfer( + address _l1Token, + address _to, + uint256 _amount, + uint256, /* _maxGas */ + uint256, /* _gasPriceBid */ + bytes calldata _data + ) public payable override returns (bytes memory res) { + if (withdrawalsPaused) { + revert L2USDCGateway_WithdrawalsPaused(); + } + return super.outboundTransfer(_l1Token, _to, _amount, 0, 0, _data); + } + + /** + * @notice Only parent chain - child chain USDC token pair is supported + */ + function calculateL2TokenAddress(address l1ERC20) public view override returns (address) { + if (l1ERC20 != l1USDC) { + // invalid L1 usdc address + return address(0); + } + return l2USDC; + } + + function inboundEscrowTransfer(address _l2Address, address _dest, uint256 _amount) + internal + override + { + IFiatToken(_l2Address).mint(_dest, _amount); + } + + function outboundEscrowTransfer(address _l2Token, address _from, uint256 _amount) + internal + override + returns (uint256) + { + // fetch the USDC tokens from the user and then burn them + IERC20(_l2Token).safeTransferFrom(_from, address(this), _amount); + IFiatToken(_l2Token).burn(_amount); + + return _amount; + } + + /** + * @notice Withdraw back the USDC if child chain side is not set up properly + */ + function handleNoContract( + address l1ERC20, + address, /* expectedL2Address */ + address _from, + address, /* _to */ + uint256 _amount, + bytes memory /* deployData */ + ) internal override returns (bool shouldHalt) { + // it is assumed that the custom token is deployed to child chain before deposits are made + triggerWithdrawal(l1ERC20, address(this), _from, _amount, ""); + return true; + } + + /** + * @notice We need to override this function because base implementation assumes that L2 token implements + * `l1Address()` function from IArbToken interface. In the case of USDC gateway IArbToken logic is + * part of this contract, so we just check that addresses match the expected L1 and L2 USDC address. + */ + function _isValidTokenAddress(address _l1Address, address _expectedL2Address) + internal + view + override + returns (bool) + { + return _l1Address == l1USDC && _expectedL2Address == l2USDC; + } +} diff --git a/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol index 8ac88717a4..bdef669b4b 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol @@ -224,10 +224,11 @@ abstract contract L1ArbitrumGateway is * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed + * The msg.sender that calls this method, or its L2 alias if it has code in L1, will be set to the callValueRefundAddress; + * this means it can cancel the retryable ticket if its auto-redeem fails, and also that it receives the l2 callvalue refund. * @param _l1Token L1 address of ERC20 * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2 - * @param _to Account to be credited with the tokens in the L2 (can be the user's L2 account or a contract), not subject to L2 aliasing - This account, or its L2 alias if it have code in L1, will also be able to cancel the retryable ticket and receive callvalue refund + * @param _to Account to be credited with the tokens in the L2 (can be an EOA or a contract), not subject to L2 aliasing * @param _amount Token Amount * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution * @param _gasPriceBid Gas price for L2 execution diff --git a/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol b/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol index f5aef49d97..ec356564fb 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol @@ -294,10 +294,11 @@ contract L1GatewayRouter is * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed + * The msg.sender that calls this method, or its L2 alias if it has code in L1, will be set to the callValueRefundAddress; + * this means it can cancel the retryable ticket if its auto-redeem fails, and also that it receives the l2 callvalue refund. * @param _token L1 address of ERC20 * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2 - * @param _to Account to be credited with the tokens in the L2 (can be the user's L2 account or a contract), not subject to L2 aliasing - This account, or its L2 alias if it have code in L1, will also be able to cancel the retryable ticket and receive callvalue refund + * @param _to Account to be credited with the tokens in the L2 (can be an EOA or a contract), not subject to L2 aliasing. * @param _amount Token Amount * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution * @param _gasPriceBid Gas price for L2 execution diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol new file mode 100644 index 0000000000..f032a751f7 --- /dev/null +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import {L1USDCGateway} from "./L1USDCGateway.sol"; +import {IERC20Inbox} from "../L1ArbitrumMessenger.sol"; +import {IERC20Bridge} from "../../libraries/IERC20Bridge.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +/** + * @title Custom gateway for USDC implementing Bridged USDC Standard. + * @notice Reference to the Circle's Bridged USDC Standard: + * https://github.com/circlefin/stablecoin-evm/blob/master/doc/bridged_USDC_standard.md + * + * @dev This contract can be used on new Orbit chains which want to provide USDC + * bridging solution and keep the possibility to upgrade to native USDC at + * some point later. This solution will NOT be used in existing Arbitrum chains. + * + * Child chain custom gateway to be used along this parent chain custom gateway is L2USDCGateway. + * This custom gateway differs from standard gateway in the following ways: + * - it supports a single parent chain - child chain USDC token pair + * - it is ownable + * - owner can pause and unpause deposits + * - owner can set a burner address + * - owner can set the amount of USDC tokens to be burned by burner + * - burner can trigger burning the amount of USDC tokens locked in the gateway that matches the L2 supply + * + * This contract is to be used on chains where custom fee token is used. If chain is using + * ETH as native token then use L1USDCGateway instead. + */ +contract L1OrbitUSDCGateway is L1USDCGateway { + using SafeERC20 for IERC20; + + function _parseUserEncodedData(bytes memory data) + internal + pure + override + returns (uint256 maxSubmissionCost, bytes memory callHookData, uint256 tokenTotalFeeAmount) + { + (maxSubmissionCost, callHookData, tokenTotalFeeAmount) = + abi.decode(data, (uint256, bytes, uint256)); + } + + function _initiateDeposit( + address _refundTo, + address _from, + uint256, // _amount, this info is already contained in _data + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + uint256 tokenTotalFeeAmount, + bytes memory _data + ) internal override returns (uint256) { + return sendTxToL2CustomRefund( + inbox, + counterpartGateway, + _refundTo, + _from, + tokenTotalFeeAmount, + 0, + L2GasParams({ + _maxSubmissionCost: _maxSubmissionCost, + _maxGas: _maxGas, + _gasPriceBid: _gasPriceBid + }), + _data + ); + } + + function _createRetryable( + address _inbox, + address _to, + address _refundTo, + address _user, + uint256 _totalFeeAmount, + uint256 _l2CallValue, + uint256 _maxSubmissionCost, + uint256 _maxGas, + uint256 _gasPriceBid, + bytes memory _data + ) internal override returns (uint256) { + { + // Transfer native token amount needed to pay for retryable fees to the inbox. + // Fee tokens will be transferred from user who initiated the action - that's `_user` account in + // case call was routed by router, or msg.sender in case gateway's entrypoint was called directly. + address nativeFeeToken = IERC20Bridge(address(getBridge(_inbox))).nativeToken(); + uint256 inboxNativeTokenBalance = IERC20(nativeFeeToken).balanceOf(_inbox); + if (inboxNativeTokenBalance < _totalFeeAmount) { + address transferFrom = isRouter(msg.sender) ? _user : msg.sender; + IERC20(nativeFeeToken).safeTransferFrom( + transferFrom, _inbox, _totalFeeAmount - inboxNativeTokenBalance + ); + } + } + + return IERC20Inbox(_inbox).createRetryableTicket( + _to, + _l2CallValue, + _maxSubmissionCost, + _refundTo, + _user, + _maxGas, + _gasPriceBid, + _totalFeeAmount, + _data + ); + } +} diff --git a/contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol new file mode 100644 index 0000000000..edc1dd0e19 --- /dev/null +++ b/contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.4; + +import { + L1ArbitrumExtendedGateway, + L1ArbitrumGateway, + ITokenGateway, + TokenGateway +} from "./L1ArbitrumExtendedGateway.sol"; +import {IFiatToken, IFiatTokenProxy} from "../../libraries/IFiatToken.sol"; + +/** + * @title Custom gateway for USDC implementing Bridged USDC Standard. + * @notice Reference to the Circle's Bridged USDC Standard: + * https://github.com/circlefin/stablecoin-evm/blob/master/doc/bridged_USDC_standard.md + * + * @dev This contract can be used on new Orbit chains which want to provide USDC + * bridging solution and keep the possibility to upgrade to native USDC at + * some point later. This solution will NOT be used in existing Arbitrum chains. + * + * Child chain custom gateway to be used along this parent chain custom gateway is L2USDCGateway. + * This custom gateway differs from standard gateway in the following ways: + * - it supports a single parent chain - child chain USDC token pair + * - it is ownable + * - owner can pause and unpause deposits + * - owner can set a burner address + * - owner can set the amount of USDC tokens to be burned by burner. Owner is trusted to this correctly and not frontrun the burning. + * - burner can trigger burning the amount of USDC tokens locked in the gateway that matches the L2 supply + * + * This contract is to be used on chains where ETH is the native token. If chain is using + * custom fee token then use L1OrbitUSDCGateway instead. + * + * NOTE: before depositing funds, make sure that recipient address is not blacklisted on the child chain. + * Also, make sure that USDC token itself is not paused. Otherwise funds might get stuck. + */ +contract L1USDCGateway is L1ArbitrumExtendedGateway { + address public l1USDC; + address public l2USDC; + address public owner; + address public burner; + bool public depositsPaused; + uint256 public burnAmount; + + event DepositsPaused(); + event DepositsUnpaused(); + event GatewayUsdcBurned(uint256 amount); + event BurnerSet(address indexed burner); + event BurnAmountSet(uint256 amount); + + error L1USDCGateway_DepositsAlreadyPaused(); + error L1USDCGateway_DepositsAlreadyUnpaused(); + error L1USDCGateway_DepositsPaused(); + error L1USDCGateway_DepositsNotPaused(); + error L1USDCGateway_InvalidL1USDC(); + error L1USDCGateway_InvalidL2USDC(); + error L1USDCGateway_NotOwner(); + error L1USDCGateway_InvalidOwner(); + error L1USDCGateway_NotBurner(); + error L1USDCGateway_BurnAmountNotSet(); + + modifier onlyOwner() { + if (msg.sender != owner) { + revert L1USDCGateway_NotOwner(); + } + _; + } + + function initialize( + address _l2Counterpart, + address _l1Router, + address _inbox, + address _l1USDC, + address _l2USDC, + address _owner + ) public { + if (_l1USDC == address(0)) { + revert L1USDCGateway_InvalidL1USDC(); + } + if (_l2USDC == address(0)) { + revert L1USDCGateway_InvalidL2USDC(); + } + if (_owner == address(0)) { + revert L1USDCGateway_InvalidOwner(); + } + L1ArbitrumGateway._initialize(_l2Counterpart, _l1Router, _inbox); + l1USDC = _l1USDC; + l2USDC = _l2USDC; + owner = _owner; + } + + /** + * @notice Pauses deposits. This can only be called by the owner. + * @dev Pausing is prerequisite for burning escrowed USDC tokens. Incoming withdrawals are not affected. + * Pausing the withdrawals needs to be done separately on the child chain. + */ + function pauseDeposits() external onlyOwner { + if (depositsPaused) { + revert L1USDCGateway_DepositsAlreadyPaused(); + } + depositsPaused = true; + + emit DepositsPaused(); + } + + /** + * @notice Unpauses deposits. This can only be called by the owner. + */ + function unpauseDeposits() external onlyOwner { + if (!depositsPaused) { + revert L1USDCGateway_DepositsAlreadyUnpaused(); + } + depositsPaused = false; + + emit DepositsUnpaused(); + } + + /** + * @notice Owner sets a new burner. + */ + function setBurner(address newBurner) external onlyOwner { + burner = newBurner; + emit BurnerSet(newBurner); + } + + /** + * @notice Owner sets the amount of USDC tokens to be burned by burner account. + * @dev This amount should match the L2 supply of bridged USDC. But it's not enforced, so burner + * should verify that correct amount is set before proceeding with burning. + */ + function setBurnAmount(uint256 _burnAmount) external onlyOwner { + burnAmount = _burnAmount; + emit BurnAmountSet(_burnAmount); + } + + /** + * @notice Burns the USDC tokens escrowed in the gateway. + * @dev Can be called by burner when deposits are paused and when owner has set the burn amount. + * Owner is trusted to correctly set the burn amount and to not frontrun the burning by + * modifying the burn amount. + * Function signature complies by Bridged USDC Standard. + */ + function burnLockedUSDC() external { + if (msg.sender != burner) { + revert L1USDCGateway_NotBurner(); + } + if (!depositsPaused) { + revert L1USDCGateway_DepositsNotPaused(); + } + uint256 _burnAmount = burnAmount; + if (_burnAmount == 0) { + revert L1USDCGateway_BurnAmountNotSet(); + } + + burnAmount = 0; + IFiatToken(l1USDC).burn(_burnAmount); + emit GatewayUsdcBurned(_burnAmount); + } + + /** + * @notice Sets a new owner. + */ + function setOwner(address newOwner) external onlyOwner { + if (newOwner == address(0)) { + revert L1USDCGateway_InvalidOwner(); + } + owner = newOwner; + } + + /** + * @notice entrypoint for depositing USDC, can be used only if deposits are not paused. + */ + function outboundTransferCustomRefund( + address _l1Token, + address _refundTo, + address _to, + uint256 _amount, + uint256 _maxGas, + uint256 _gasPriceBid, + bytes calldata _data + ) public payable override returns (bytes memory res) { + if (depositsPaused) { + revert L1USDCGateway_DepositsPaused(); + } + return super.outboundTransferCustomRefund( + _l1Token, _refundTo, _to, _amount, _maxGas, _gasPriceBid, _data + ); + } + + /** + * @notice only parent chain - child chain USDC token pair is supported + */ + function calculateL2TokenAddress(address l1ERC20) + public + view + override(ITokenGateway, TokenGateway) + returns (address) + { + if (l1ERC20 != l1USDC) { + // invalid L1 USDC address + return address(0); + } + return l2USDC; + } +} diff --git a/contracts/tokenbridge/libraries/IFiatToken.sol b/contracts/tokenbridge/libraries/IFiatToken.sol new file mode 100644 index 0000000000..acca9da4f7 --- /dev/null +++ b/contracts/tokenbridge/libraries/IFiatToken.sol @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: MIT +// solhint-disable-next-line compiler-version +pragma solidity >0.6.0 <0.9.0; + +/** + * @title IFiatToken + * @dev Interface contains functions from Circle's referent implementation of the USDC + * Ref: https://github.com/circlefin/stablecoin-evm + * + * This interface is used in the L1USDCGateway, L1OrbitUSDCGateway and L2USDCGateway contracts. + */ +interface IFiatToken { + function allowance(address owner, address spender) external view returns (uint256); + function approve(address spender, uint256 value) external returns (bool); + function authorizationState(address authorizer, bytes32 nonce) external view returns (bool); + function balanceOf(address account) external view returns (uint256); + function blacklist(address _account) external; + function blacklister() external view returns (address); + function burn(uint256 _amount) external; + function cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s) + external; + function cancelAuthorization(address authorizer, bytes32 nonce, bytes memory signature) + external; + function configureMinter(address minter, uint256 minterAllowedAmount) external returns (bool); + function currency() external view returns (string memory); + function decimals() external view returns (uint8); + function decreaseAllowance(address spender, uint256 decrement) external returns (bool); + function increaseAllowance(address spender, uint256 increment) external returns (bool); + function initialize( + string memory tokenName, + string memory tokenSymbol, + string memory tokenCurrency, + uint8 tokenDecimals, + address newMasterMinter, + address newPauser, + address newBlacklister, + address newOwner + ) external; + function initializeV2(string memory newName) external; + function initializeV2_1(address lostAndFound) external; + function initializeV2_2(address[] memory accountsToBlacklist, string memory newSymbol) + external; + function isBlacklisted(address _account) external view returns (bool); + function isMinter(address account) external view returns (bool); + function masterMinter() external view returns (address); + function mint(address _to, uint256 _amount) external returns (bool); + function minterAllowance(address minter) external view returns (uint256); + function name() external view returns (string memory); + function nonces(address owner) external view returns (uint256); + function owner() external view returns (address); + function pause() external; + function paused() external view returns (bool); + function pauser() external view returns (address); + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + bytes memory signature + ) external; + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; + function receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + bytes memory signature + ) external; + function receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) external; + function removeMinter(address minter) external returns (bool); + function rescueERC20(address tokenContract, address to, uint256 amount) external; + function rescuer() external view returns (address); + function symbol() external view returns (string memory); + function totalSupply() external view returns (uint256); + function transfer(address to, uint256 value) external returns (bool); + function transferFrom(address from, address to, uint256 value) external returns (bool); + function transferOwnership(address newOwner) external; + function transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + bytes memory signature + ) external; + function transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) external; + function unBlacklist(address _account) external; + function unpause() external; + function updateBlacklister(address _newBlacklister) external; + function updateMasterMinter(address _newMasterMinter) external; + function updatePauser(address _newPauser) external; + function updateRescuer(address newRescuer) external; + function version() external pure returns (string memory); +} + +/** + * @title IFiatTokenProxy + * @dev Interface contains functions from Circle's referent implementation of the USDC proxy + * Ref: https://github.com/circlefin/stablecoin-evm + * + * This interface is used in the L1USDCGateway, L1OrbitUSDCGateway and L2USDCGateway contracts. + */ +interface IFiatTokenProxy { + function admin() external view returns (address); + function changeAdmin(address newAdmin) external; + function implementation() external view returns (address); + function upgradeTo(address newImplementation) external; + function upgradeToAndCall(address newImplementation, bytes memory data) external payable; +} diff --git a/foundry.toml b/foundry.toml index ba6691c9fe..a41af7094b 100644 --- a/foundry.toml +++ b/foundry.toml @@ -7,6 +7,7 @@ cache_path = 'forge-cache' optimizer = true optimizer_runs = 100 via_ir = false +fs_permissions = [{ access = "read", path = "node_modules/@offchainlabs/stablecoin-evm"}] [fmt] number_underscore = 'thousands' diff --git a/package.json b/package.json index 42067a24ec..e958d3dd01 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@arbitrum/token-bridge-contracts", - "version": "1.2.2", + "version": "1.2.3", "license": "Apache-2.0", "scripts": { "prepublishOnly": "hardhat clean && hardhat compile", @@ -22,12 +22,14 @@ "test:storage": "./scripts/storage_layout_test.bash", "test:signatures": "./scripts/signatures_test.bash", "test:mutation": "ts-node test-mutation/gambitTester.ts", + "test:unused:errors": "./test/unused-errors/find_unused_errors.sh", "deploy:local:token-bridge": "ts-node ./scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts", "deploy:token-bridge-creator": "ts-node ./scripts/deployment/deployTokenBridgeCreator.ts", "create:token-bridge": "ts-node ./scripts/deployment/createTokenBridge.ts", "test:tokenbridge:deployment": "hardhat test test-e2e/tokenBridgeDeploymentTest.ts", "test:creation-code": "hardhat test test-e2e/creationCodeTest.ts", "blockscout:verify": "hardhat run ./scripts/orbitVerifyOnBlockscout.ts", + "deploy:usdc-token-bridge": "hardhat run scripts/usdc-bridge-deployment/deployUsdcBridge.ts", "typechain": "hardhat typechain", "deploy:tokenbridge": "hardhat run scripts/deploy_token_bridge_l1.ts --network mainnet", "gen:uml": "sol2uml ./contracts/tokenbridge/arbitrum,./contracts/tokenbridge/ethereum,./contracts/tokenbridge/libraries -o ./gatewayUML.svg", @@ -42,12 +44,13 @@ ], "dependencies": { "@arbitrum/nitro-contracts": "1.1.1", + "@offchainlabs/stablecoin-evm": "1.0.0-orbit-alpha.2", "@offchainlabs/upgrade-executor": "1.1.0-beta.0", "@openzeppelin/contracts": "4.8.3", "@openzeppelin/contracts-upgradeable": "4.8.3" }, "devDependencies": { - "@arbitrum/sdk": "^3.1.3", + "@arbitrum/sdk": "^3.5.1", "@nomiclabs/hardhat-ethers": "^2.0.1", "@nomiclabs/hardhat-etherscan": "^3.1.0", "@nomiclabs/hardhat-waffle": "^2.0.1", diff --git a/scripts/local-deployment/localDeploymentLib.ts b/scripts/local-deployment/localDeploymentLib.ts index a1dff54c9a..3e08fb498f 100644 --- a/scripts/local-deployment/localDeploymentLib.ts +++ b/scripts/local-deployment/localDeploymentLib.ts @@ -10,7 +10,6 @@ import { getEstimateForDeployingFactory, registerGateway, } from '../atomicTokenBridgeDeployer' -import { l2Networks } from '@arbitrum/sdk/dist/lib/dataEntities/networks' import { ERC20__factory, IOwnable__factory, @@ -75,39 +74,29 @@ export const setupTokenBridgeInLocalEnv = async () => { new ethers.providers.JsonRpcProvider(childRpc) ) + /// register networks const { l1Network, l2Network: coreL2Network } = await getLocalNetworks( parentRpc, childRpc, rollupAddress ) - - // register - needed for retryables - const existingL2Network = l2Networks[coreL2Network.chainID.toString()] - if (!existingL2Network) { - addCustomNetwork({ - customL1Network: l1Network, - customL2Network: { - ...coreL2Network, - tokenBridge: { - l1CustomGateway: '', - l1ERC20Gateway: '', - l1GatewayRouter: '', - l1MultiCall: '', - l1ProxyAdmin: '', - l1Weth: '', - l1WethGateway: '', - - l2CustomGateway: '', - l2ERC20Gateway: '', - l2GatewayRouter: '', - l2Multicall: '', - l2ProxyAdmin: '', - l2Weth: '', - l2WethGateway: '', - }, - }, - }) + const _l1Network = l1Network as L2Network + const ethLocal: L1Network = { + blockTime: 10, + chainID: _l1Network.partnerChainID, + explorerUrl: '', + isCustom: true, + name: 'EthLocal', + partnerChainIDs: [_l1Network.chainID], + isArbitrum: false, } + addCustomNetwork({ + customL1Network: ethLocal, + customL2Network: _l1Network, + }) + addCustomNetwork({ + customL2Network: coreL2Network, + }) // prerequisite - deploy L1 creator and set templates console.log('Deploying L1TokenBridgeCreator') @@ -207,13 +196,73 @@ export const getLocalNetworks = async ( l2Url: string, rollupAddress?: string ): Promise<{ - l1Network: L1Network - l2Network: Omit + l1Network: L1Network | L2Network + l2Network: L2Network }> => { const l1Provider = new JsonRpcProvider(l1Url) const l2Provider = new JsonRpcProvider(l2Url) - let deploymentData: string + const l1NetworkInfo = await l1Provider.getNetwork() + const l2NetworkInfo = await l2Provider.getNetwork() + + /// get parent chain info + const container = execSync( + 'docker ps --filter "name=sequencer" --format "{{.Names}}"' + ) + .toString() + .trim() + const l2DeploymentData = execSync( + `docker exec ${container} cat /config/deployment.json` + ).toString() + const l2Data = JSON.parse(l2DeploymentData) as { + bridge: string + inbox: string + ['sequencer-inbox']: string + rollup: string + } + + const l1Network: L1Network | L2Network = { + partnerChainID: 1337, + partnerChainIDs: [l2NetworkInfo.chainId], + isArbitrum: true, + confirmPeriodBlocks: 20, + retryableLifetimeSeconds: 7 * 24 * 60 * 60, + nitroGenesisBlock: 0, + nitroGenesisL1Block: 0, + depositTimeout: 900000, + chainID: 412346, + explorerUrl: '', + isCustom: true, + name: 'ArbLocal', + blockTime: 0.25, + ethBridge: { + bridge: l2Data.bridge, + inbox: l2Data.inbox, + outbox: '', + rollup: l2Data.rollup, + sequencerInbox: l2Data['sequencer-inbox'], + }, + tokenBridge: { + l1CustomGateway: '', + l1ERC20Gateway: '', + l1GatewayRouter: '', + l1MultiCall: '', + l1ProxyAdmin: '', + l1Weth: '', + l1WethGateway: '', + + l2CustomGateway: '', + l2ERC20Gateway: '', + l2GatewayRouter: '', + l2Multicall: '', + l2ProxyAdmin: '', + l2Weth: '', + l2WethGateway: '', + }, + } + + /// get L3 info + let deploymentData: string let data = { bridge: '', inbox: '', @@ -246,28 +295,14 @@ export const getLocalNetworks = async ( data.rollup = rollupAddress! } - const rollup = RollupAdminLogic__factory.connect(data.rollup, l1Provider) - const confirmPeriodBlocks = await rollup.confirmPeriodBlocks() - const bridge = Bridge__factory.connect(data.bridge, l1Provider) const outboxAddr = await bridge.allowedOutboxList(0) - const l1NetworkInfo = await l1Provider.getNetwork() - const l2NetworkInfo = await l2Provider.getNetwork() - - const l1Network: L1Network = { - blockTime: 10, - chainID: l1NetworkInfo.chainId, - explorerUrl: '', - isCustom: true, - name: 'EthLocal', - partnerChainIDs: [l2NetworkInfo.chainId], - isArbitrum: false, - } - - const l2Network: Omit = { + const l2Network: L2Network = { + partnerChainID: l1NetworkInfo.chainId, + partnerChainIDs: [], chainID: l2NetworkInfo.chainId, - confirmPeriodBlocks: confirmPeriodBlocks.toNumber(), + confirmPeriodBlocks: 20, ethBridge: { bridge: data.bridge, inbox: data.inbox, @@ -278,12 +313,29 @@ export const getLocalNetworks = async ( explorerUrl: '', isArbitrum: true, isCustom: true, - name: 'ArbLocal', - partnerChainID: l1NetworkInfo.chainId, + blockTime: 0.25, + name: 'OrbitLocal', retryableLifetimeSeconds: 7 * 24 * 60 * 60, nitroGenesisBlock: 0, nitroGenesisL1Block: 0, depositTimeout: 900000, + tokenBridge: { + l1CustomGateway: '', + l1ERC20Gateway: '', + l1GatewayRouter: '', + l1MultiCall: '', + l1ProxyAdmin: '', + l1Weth: '', + l1WethGateway: '', + + l2CustomGateway: '', + l2ERC20Gateway: '', + l2GatewayRouter: '', + l2Multicall: '', + l2ProxyAdmin: '', + l2Weth: '', + l2WethGateway: '', + }, } return { l1Network, diff --git a/scripts/signatures_test.bash b/scripts/signatures_test.bash index f728e5d512..b4e0fb1636 100755 --- a/scripts/signatures_test.bash +++ b/scripts/signatures_test.bash @@ -1,6 +1,6 @@ #!/bin/bash output_dir="./test/signatures" -for CONTRACTNAME in L1ERC20Gateway L1CustomGateway L1ReverseCustomGateway L1WethGateway L2ERC20Gateway L2CustomGateway L2ReverseCustomGateway L2WethGateway L1GatewayRouter L2GatewayRouter StandardArbERC20 L1AtomicTokenBridgeCreator L1TokenBridgeRetryableSender L2AtomicTokenBridgeFactory L1OrbitCustomGateway L1OrbitERC20Gateway L1OrbitGatewayRouter L1OrbitReverseCustomGateway +for CONTRACTNAME in L1ERC20Gateway L1CustomGateway L1ReverseCustomGateway L1WethGateway L2ERC20Gateway L2CustomGateway L2ReverseCustomGateway L2WethGateway L1GatewayRouter L2GatewayRouter StandardArbERC20 L1AtomicTokenBridgeCreator L1TokenBridgeRetryableSender L2AtomicTokenBridgeFactory L1OrbitCustomGateway L1OrbitERC20Gateway L1OrbitGatewayRouter L1OrbitReverseCustomGateway L1USDCGateway L1OrbitUSDCGateway L2USDCGateway do echo "Checking for signature changes in $CONTRACTNAME" [ -f "$output_dir/$CONTRACTNAME" ] && mv "$output_dir/$CONTRACTNAME" "$output_dir/$CONTRACTNAME-old" diff --git a/scripts/storage_layout_test.bash b/scripts/storage_layout_test.bash index 850b71460f..ceb28b7006 100755 --- a/scripts/storage_layout_test.bash +++ b/scripts/storage_layout_test.bash @@ -1,6 +1,6 @@ #!/bin/bash output_dir="./test/storage" -for CONTRACTNAME in L1ERC20Gateway L1CustomGateway L1ReverseCustomGateway L1WethGateway L2ERC20Gateway L2CustomGateway L2ReverseCustomGateway L2WethGateway L1GatewayRouter L2GatewayRouter StandardArbERC20 +for CONTRACTNAME in L1ERC20Gateway L1CustomGateway L1ReverseCustomGateway L1WethGateway L2ERC20Gateway L2CustomGateway L2ReverseCustomGateway L2WethGateway L1GatewayRouter L2GatewayRouter StandardArbERC20 L1AtomicTokenBridgeCreator L1TokenBridgeRetryableSender L2AtomicTokenBridgeFactory L1OrbitCustomGateway L1OrbitERC20Gateway L1OrbitGatewayRouter L1OrbitReverseCustomGateway L1USDCGateway L1OrbitUSDCGateway L2USDCGateway do echo "Checking storage change of $CONTRACTNAME" [ -f "$output_dir/$CONTRACTNAME" ] && mv "$output_dir/$CONTRACTNAME" "$output_dir/$CONTRACTNAME-old" diff --git a/scripts/usdc-bridge-deployment/README.md b/scripts/usdc-bridge-deployment/README.md new file mode 100644 index 0000000000..bc0fc782aa --- /dev/null +++ b/scripts/usdc-bridge-deployment/README.md @@ -0,0 +1,82 @@ +# Bridged USDC standard implementation for Orbit chains + +## Background + +Circle’s Bridged USDC Standard is a specification and process for deploying a bridged form of USDC on EVM blockchains with optionality for Circle to seamlessly upgrade to native issuance in the future. + +We provide custom USDC gateway implementation (for parent and child chain) that follows Bridged USDC Standard. These contracts can be used by new Orbit chains. This solution will NOT be used in existing Arbitrum chains. On parent chain contract `L1USDCGateway` is used in case child chain uses ETH as native currency, or `L1OrbitUSDCGateway` in case child chain uses custom fee token. On child chain `L2USDCGateway` is used. For the USDC token contracts, Circle's referent implementation is used. + +This doc describes how to deploy USDC bridge compatible with both Arbitrum's token bridge and Circle’s Bridged USDC Standard.Also steps for transition to native USDC issuance are provided. + +## Assumptions + +It is assumed there is already USDC token deployed and used on the parent chain. + +Also, it is assumed the standard Orbit chain ownership system is used, ie. UpgradeExecutor is the owner of the ownable contracts and there is an EOA or multisig which has executor role on the UpgradeExecutor. + +Note: throughout the docs and code, terms `L1` and `L2` are used interchangeably with `parent chain` and `child chain`. They have the same meaning, ie. if an Orbit chain is deployed on top of ArbitrumOne then ArbitrumOne is `L1`/`parent chain`, while Orbit is `L2`/`child chain` + +## Deployment steps + +Checkout target code, install dependencies and build + +``` +cd token-bridge-contracts +yarn install +yarn build +``` + +Populate .env based on `env.example` in this directory + +``` +PARENT_RPC= +PARENT_DEPLOYER_KEY= +CHILD_RPC= +CHILD_DEPLOYER_KEY= +L1_ROUTER= +L2_ROUTER= +INBOX= +L1_USDC= +## OPTIONAL arg. If set, script will register the gateway, otherwise it will store TX payload in a file +ROLLUP_OWNER_KEY= +``` + +Run the script + +``` +yarn deploy:usdc-token-bridge +``` + +Script will do the following: + +- load deployer wallets for L1 and L2 +- register L1 and L2 networks in SDK +- deploy new L1 and L2 proxy admins +- deploy bridged (L2) USDC using the Circle's implementation +- init L2 USDC +- deploy L1 USDC gateway +- deploy L2 USDC gateway +- init both gateways +- if `ROLLUP_OWNER_KEY` is provided, register the gateway in the router through the UpgradeExecutor +- if `ROLLUP_OWNER_KEY` is not provided, prepare calldata and store it in `registerUsdcGatewayTx.json` file +- set minter role to L2 USDC gateway with max allowance + +Now new USDC gateways can be used to deposit/withdraw USDC. And everything is in place to support transtition to native USDC issuance, in case Circle and Orbit chain owner agree to it. + +## Transition to native USDC + +Once transition to native USDC is agreed on, following steps are required: + +- L1 gateway owner pauses deposits on parent chain by calling `pauseDeposits()` +- L2 gateway owner pauses withdrawals on child chain by calling `pauseWithdrawals()` +- master minter removes the minter role from the child chain gateway + - NOTE: there should be no in-flight deposits when minter role is revoked. If there are any, they should be finalized first. That can be done by anyone by claiming the claimable failed retryable tickets which do the USDC depositing +- L1 gateway owner sets Circle's account as burner on the parent chain gateway using `setBurner(address)` +- L1 gateway owner reads the total supply of USDC on the child chain, and then invokes `setBurnAmount(uint256)` on the parent child gateway where the amount matches the total supply +- USDC masterMinter gives minter role with 0 allowance to L1 gateway, so the burn can be executed +- on the child chain, L2 gateway owner calls the `setUsdcOwnershipTransferrer(address)` to set the account (provided and controlled by Circle) which will be able to transfer the bridged USDC ownership and proxy admin +- if not already owned by gateway, L2 USDC owner transfers ownership to gateway, and proxy admin transfers admin rights to gateway +- Circle uses `usdcOwnershipTransferrer` account to trigger `transferUSDCRoles(address)` which will set caller as USDC proxy admin and will transfer USDC ownership to the provided address +- Circle calls `burnLockedUSDC()` on the L1 gateway using `burner` account to burn the `burnAmount` of USDC + - remaining USDC will be cleared off when remaining in-flight USDC withdrawals are executed, if any + - L1 gateway owner is trusted to not frontrun this TX to modify the burning amount diff --git a/scripts/usdc-bridge-deployment/deployUsdcBridge.ts b/scripts/usdc-bridge-deployment/deployUsdcBridge.ts new file mode 100644 index 0000000000..68fb06e666 --- /dev/null +++ b/scripts/usdc-bridge-deployment/deployUsdcBridge.ts @@ -0,0 +1,789 @@ +import { BigNumber, Contract, ContractTransaction, Wallet } from 'ethers' +import { ethers } from 'hardhat' +import { + ERC20__factory, + IBridge__factory, + IERC20__factory, + IERC20Bridge__factory, + IFiatToken__factory, + IFiatTokenProxy__factory, + IInboxBase__factory, + L1GatewayRouter__factory, + L1OrbitGatewayRouter__factory, + L1OrbitUSDCGateway, + L1OrbitUSDCGateway__factory, + L1USDCGateway, + L1USDCGateway__factory, + L2GatewayRouter__factory, + L2USDCGateway, + L2USDCGateway__factory, + ProxyAdmin, + ProxyAdmin__factory, + TransparentUpgradeableProxy__factory, + UpgradeExecutor__factory, +} from '../../build/types' +import { JsonRpcProvider, Provider } from '@ethersproject/providers' +import dotenv from 'dotenv' +import { + abi as SigCheckerAbi, + bytecode as SigCheckerBytecode, +} from '@offchainlabs/stablecoin-evm/artifacts/hardhat/contracts/util/SignatureChecker.sol/SignatureChecker.json' +import { + abi as UsdcAbi, + bytecode as UsdcBytecode, +} from '@offchainlabs/stablecoin-evm/artifacts/hardhat/contracts/v2/FiatTokenV2_2.sol/FiatTokenV2_2.json' +import { + abi as UsdcProxyAbi, + bytecode as UsdcProxyBytecode, +} from '@offchainlabs/stablecoin-evm/artifacts/hardhat/contracts/v1/FiatTokenProxy.sol/FiatTokenProxy.json' +import { + abi as MasterMinterAbi, + bytecode as MasterMinterBytecode, +} from '@offchainlabs/stablecoin-evm/artifacts/hardhat/contracts/minting/MasterMinter.sol/MasterMinter.json' +import { + addCustomNetwork, + L1Network, + L1ToL2MessageGasEstimator, + L1ToL2MessageStatus, + L1TransactionReceipt, + L2Network, +} from '@arbitrum/sdk' +import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' +import { getBaseFee } from '@arbitrum/sdk/dist/lib/utils/lib' +import fs from 'fs' + +dotenv.config() + +const REGISTRATION_TX_FILE = 'registerUsdcGatewayTx.json' + +main().then(() => console.log('Done.')) + +/** + * USDC bridge deployment script. Script will do the following: + * - load deployer wallets for L1 and L2 + * - register L1 and L2 networks in SDK + * - deploy new L1 and L2 proxy admins + * - deploy bridged (L2) USDC using the Circle's implementation + * - init L2 USDC + * - deploy L1 USDC gateway + * - deploy L2 USDC gateway + * - init both gateways + * - if `ROLLUP_OWNER_KEY` is provided, register the gateway in the router through the UpgradeExecutor + * - if `ROLLUP_OWNER_KEY` is not provided, prepare calldata and store it in `registerUsdcGatewayTx.json` file + * - set minter role to L2 USDC gateway with max allowance + */ +async function main() { + console.log('Starting USDC bridge deployment') + + _checkEnvVars() + + const { deployerL1, deployerL2 } = await _loadWallets() + console.log('Loaded deployer wallets') + + const inbox = process.env['INBOX'] as string + await _registerNetworks(deployerL1.provider, deployerL2.provider, inbox) + console.log('Networks registered in SDK') + + const proxyAdminL1 = await _deployProxyAdmin(deployerL1) + console.log('L1 ProxyAdmin deployed: ', proxyAdminL1.address) + + const proxyAdminL2 = await _deployProxyAdmin(deployerL2) + console.log('L2 ProxyAdmin deployed: ', proxyAdminL2.address) + + const { l2Usdc, masterMinter } = await _deployBridgedUsdc( + deployerL2, + proxyAdminL2 + ) + console.log('Bridged (L2) USDC deployed: ', l2Usdc.address) + + const l1UsdcGateway = await _deployL1UsdcGateway( + deployerL1, + proxyAdminL1, + inbox + ) + console.log('L1 USDC gateway deployed: ', l1UsdcGateway.address) + + const l2UsdcGateway = await _deployL2UsdcGateway(deployerL2, proxyAdminL2) + console.log('L2 USDC gateway deployed: ', l2UsdcGateway.address) + + await _initializeGateways( + l1UsdcGateway, + l2UsdcGateway, + inbox, + l2Usdc.address, + deployerL1, + deployerL2 + ) + console.log('Usdc gateways initialized') + + await _registerGateway( + deployerL1.provider, + deployerL2.provider, + inbox, + l1UsdcGateway.address + ) + if (!process.env['ROLLUP_OWNER_KEY']) { + console.log( + 'Multisig transaction to register USDC gateway prepared and stored in', + REGISTRATION_TX_FILE + ) + } else { + console.log('Usdc gateway registered') + } + + await _addMinterRoleToL2Gateway(l2UsdcGateway, deployerL2, masterMinter) + console.log('Minter role with max allowance added to L2 gateway') +} + +async function _loadWallets(): Promise<{ + deployerL1: Wallet + deployerL2: Wallet +}> { + const parentRpc = process.env['PARENT_RPC'] as string + const parentDeployerKey = process.env['PARENT_DEPLOYER_KEY'] as string + const childRpc = process.env['CHILD_RPC'] as string + const childDeployerKey = process.env['CHILD_DEPLOYER_KEY'] as string + + const parentProvider = new JsonRpcProvider(parentRpc) + const deployerL1 = new ethers.Wallet(parentDeployerKey, parentProvider) + + const childProvider = new JsonRpcProvider(childRpc) + const deployerL2 = new ethers.Wallet(childDeployerKey, childProvider) + + return { deployerL1, deployerL2 } +} + +async function _deployProxyAdmin(deployer: Wallet): Promise { + const proxyAdminFac = await new ProxyAdmin__factory(deployer).deploy() + return await proxyAdminFac.deployed() +} + +async function _deployBridgedUsdc( + deployerL2Wallet: Wallet, + proxyAdminL2: ProxyAdmin +) { + /// create l2 usdc behind proxy + const l2UsdcLogic = await _deployUsdcLogic(deployerL2Wallet) + const l2UsdcProxyAddress = await _deployUsdcProxy( + deployerL2Wallet, + l2UsdcLogic.address, + proxyAdminL2.address + ) + + /// deploy master minter + const masterMinterL2Fac = new ethers.ContractFactory( + MasterMinterAbi, + MasterMinterBytecode, + deployerL2Wallet + ) + const masterMinter = await masterMinterL2Fac.deploy(l2UsdcProxyAddress) + + /// init usdc proxy + const l2UsdcFiatToken = IFiatToken__factory.connect( + l2UsdcProxyAddress, + deployerL2Wallet + ) + + const pauserL2 = deployerL2Wallet + const blacklisterL2 = deployerL2Wallet + const lostAndFound = deployerL2Wallet + await ( + await l2UsdcFiatToken.initialize( + 'USDC', + 'USDC.e', + 'USD', + 6, + masterMinter.address, + pauserL2.address, + blacklisterL2.address, + deployerL2Wallet.address + ) + ).wait() + await (await l2UsdcFiatToken.initializeV2('USDC')).wait() + await (await l2UsdcFiatToken.initializeV2_1(lostAndFound.address)).wait() + await (await l2UsdcFiatToken.initializeV2_2([], 'USDC.e')).wait() + + /// verify initialization + if ( + (await l2UsdcFiatToken.name()) != 'USDC' || + (await l2UsdcFiatToken.symbol()) != 'USDC.e' || + (await l2UsdcFiatToken.currency()) != 'USD' || + (await l2UsdcFiatToken.decimals()) != 6 || + (await l2UsdcFiatToken.masterMinter()) != masterMinter.address || + (await l2UsdcFiatToken.pauser()) != pauserL2.address || + (await l2UsdcFiatToken.blacklister()) != blacklisterL2.address || + (await l2UsdcFiatToken.owner()) != deployerL2Wallet.address + ) { + throw new Error( + 'Bridged USDC initialization was not successful, might have been frontrun' + ) + } + + /// init usdc logic to dummy values + const l2UsdcLogicInit = IFiatToken__factory.connect( + l2UsdcLogic.address, + deployerL2Wallet + ) + const DEAD = '0x000000000000000000000000000000000000dEaD' + await ( + await l2UsdcLogicInit.initialize('', '', '', 0, DEAD, DEAD, DEAD, DEAD) + ).wait() + await (await l2UsdcLogicInit.initializeV2('')).wait() + await (await l2UsdcLogicInit.initializeV2_1(DEAD)).wait() + await (await l2UsdcLogicInit.initializeV2_2([], '')).wait() + + /// verify logic initialization + if ( + (await l2UsdcLogicInit.name()) != '' || + (await l2UsdcLogicInit.symbol()) != '' || + (await l2UsdcLogicInit.currency()) != '' || + (await l2UsdcLogicInit.decimals()) != 0 || + (await l2UsdcLogicInit.masterMinter()) != DEAD || + (await l2UsdcLogicInit.pauser()) != DEAD || + (await l2UsdcLogicInit.blacklister()) != DEAD || + (await l2UsdcLogicInit.owner()) != DEAD + ) { + throw new Error('Bridged USDC logic initialization was not successful') + } + + const l2Usdc = IERC20__factory.connect( + l2UsdcFiatToken.address, + deployerL2Wallet + ) + + return { l2Usdc, masterMinter } +} + +async function _deployUsdcLogic(deployer: Wallet) { + /// deploy sig checker library + const sigCheckerFac = new ethers.ContractFactory( + SigCheckerAbi, + SigCheckerBytecode, + deployer + ) + const sigCheckerLib = await sigCheckerFac.deploy() + + // link library to usdc bytecode + const bytecodeWithPlaceholder: string = UsdcBytecode + const placeholder = '__$715109b5d747ea58b675c6ea3f0dba8c60$__' + + const libAddressStripped = sigCheckerLib.address.replace(/^0x/, '') + const bridgedUsdcLogicBytecode = bytecodeWithPlaceholder + .split(placeholder) + .join(libAddressStripped) + + // deploy bridged usdc logic + const bridgedUsdcLogicFactory = new ethers.ContractFactory( + UsdcAbi, + bridgedUsdcLogicBytecode, + deployer + ) + const bridgedUsdcLogic = await bridgedUsdcLogicFactory.deploy() + + return bridgedUsdcLogic +} + +async function _deployUsdcProxy( + deployer: Wallet, + bridgedUsdcLogic: string, + proxyAdmin: string +) { + /// deploy circle's proxy used for usdc + const usdcProxyFactory = new ethers.ContractFactory( + UsdcProxyAbi, + UsdcProxyBytecode, + deployer + ) + const usdcProxy = await usdcProxyFactory.deploy(bridgedUsdcLogic) + + /// set proxy admin + await ( + await IFiatTokenProxy__factory.connect( + usdcProxy.address, + deployer + ).changeAdmin(proxyAdmin) + ).wait() + + return usdcProxy.address +} + +async function _deployL1UsdcGateway( + deployerL1: Wallet, + proxyAdmin: ProxyAdmin, + inboxAddress: string +): Promise { + const isFeeToken = + (await _getFeeToken(inboxAddress, deployerL1.provider)) != + ethers.constants.AddressZero + + const l1UsdcGatewayFactory = isFeeToken + ? await new L1OrbitUSDCGateway__factory(deployerL1).deploy() + : await new L1USDCGateway__factory(deployerL1).deploy() + const l1UsdcGatewayLogic = await l1UsdcGatewayFactory.deployed() + const tupFactory = await new TransparentUpgradeableProxy__factory( + deployerL1 + ).deploy(l1UsdcGatewayLogic.address, proxyAdmin.address, '0x') + const tup = await tupFactory.deployed() + return isFeeToken + ? L1OrbitUSDCGateway__factory.connect(tup.address, deployerL1) + : L1USDCGateway__factory.connect(tup.address, deployerL1) +} + +async function _deployL2UsdcGateway( + deployerL2: Wallet, + proxyAdmin: ProxyAdmin +): Promise { + const l2USDCCustomGatewayFactory = await new L2USDCGateway__factory( + deployerL2 + ).deploy() + const l2USDCCustomGatewayLogic = await l2USDCCustomGatewayFactory.deployed() + const tupFactory = await new TransparentUpgradeableProxy__factory( + deployerL2 + ).deploy(l2USDCCustomGatewayLogic.address, proxyAdmin.address, '0x') + const tup = await tupFactory.deployed() + return L2USDCGateway__factory.connect(tup.address, deployerL2) +} + +/** + * Initialize gateways + */ +async function _initializeGateways( + l1UsdcGateway: L1USDCGateway | L1OrbitUSDCGateway, + l2UsdcGateway: L2USDCGateway, + inbox: string, + l2Usdc: string, + deployerL1: Wallet, + deployerL2: Wallet +) { + const l1Router = process.env['L1_ROUTER'] as string + const l2Router = process.env['L2_ROUTER'] as string + const l1Usdc = process.env['L1_USDC'] as string + + /// initialize L1 gateway + const _l2CounterPart = l2UsdcGateway.address + const _owner = deployerL1.address + + await ( + await l1UsdcGateway + .connect(deployerL1) + .initialize(_l2CounterPart, l1Router, inbox, l1Usdc, l2Usdc, _owner) + ).wait() + + /// initialize L2 gateway + const _l1Counterpart = l1UsdcGateway.address + const ownerL2 = deployerL2.address + await ( + await l2UsdcGateway.initialize( + _l1Counterpart, + l2Router, + l1Usdc, + l2Usdc, + ownerL2 + ) + ).wait() + + ///// verify initialization + if ( + (await l1UsdcGateway.router()) != l1Router || + (await l1UsdcGateway.inbox()) != inbox || + (await l1UsdcGateway.l1USDC()) != l1Usdc || + (await l1UsdcGateway.l2USDC()) != l2Usdc || + (await l1UsdcGateway.owner()) != _owner || + (await l1UsdcGateway.counterpartGateway()) != _l2CounterPart + ) { + throw new Error('L1 USDC gateway initialization failed') + } + + if ( + (await l2UsdcGateway.counterpartGateway()) != _l1Counterpart || + (await l2UsdcGateway.router()) != l2Router || + (await l2UsdcGateway.l1USDC()) != l1Usdc || + (await l2UsdcGateway.l2USDC()) != l2Usdc || + (await l2UsdcGateway.owner()) != ownerL2 + ) { + throw new Error('L2 USDC gateway initialization failed') + } +} + +/** + * Do the gateway registration if rollup owner key is provided. + * Otherwise prepare the TX payload and store it in a file. + */ +async function _registerGateway( + parentProvider: Provider, + childProvider: Provider, + inbox: string, + l1UsdcGatewayAddress: string +) { + const isFeeToken = + (await _getFeeToken(inbox, parentProvider)) != ethers.constants.AddressZero + + const l1RouterAddress = process.env['L1_ROUTER'] as string + const l2RouterAddress = process.env['L2_ROUTER'] as string + const l1UsdcAddress = process.env['L1_USDC'] as string + + const l1Router = isFeeToken + ? L1OrbitGatewayRouter__factory.connect(l1RouterAddress, parentProvider) + : L1GatewayRouter__factory.connect(l1RouterAddress, parentProvider) + + /// load upgrade executor + const routerOwnerAddress = await l1Router.owner() + if (!(await _isUpgradeExecutor(routerOwnerAddress, parentProvider))) { + throw new Error('Router owner is expected to be an UpgradeExecutor') + } + const upgradeExecutor = UpgradeExecutor__factory.connect( + routerOwnerAddress, + parentProvider + ) + + /// prepare calldata for executor + const routerRegistrationData = + L2GatewayRouter__factory.createInterface().encodeFunctionData( + 'setGateway', + [[l1UsdcAddress], [l1UsdcGatewayAddress]] + ) + + const l1ToL2MessageGasEstimate = new L1ToL2MessageGasEstimator(childProvider) + const retryableParams = await l1ToL2MessageGasEstimate.estimateAll( + { + from: l1RouterAddress, + to: l2RouterAddress, + l2CallValue: BigNumber.from(0), + excessFeeRefundAddress: ethers.Wallet.createRandom().address, + callValueRefundAddress: ethers.Wallet.createRandom().address, + data: routerRegistrationData, + }, + await getBaseFee(parentProvider), + parentProvider + ) + + const maxGas = retryableParams.gasLimit + const gasPriceBid = retryableParams.maxFeePerGas.mul(3) + let maxSubmissionCost = retryableParams.maxSubmissionCost + let totalFee = maxGas.mul(gasPriceBid).add(maxSubmissionCost) + if (isFeeToken) { + totalFee = await _getPrescaledAmount( + await _getFeeToken(inbox, parentProvider), + parentProvider, + totalFee + ) + } + + const registrationCalldata = isFeeToken + ? L1OrbitGatewayRouter__factory.createInterface().encodeFunctionData( + 'setGateways(address[],address[],uint256,uint256,uint256,uint256)', + [ + [l1UsdcAddress], + [l1UsdcGatewayAddress], + maxGas, + gasPriceBid, + maxSubmissionCost, + totalFee, + ] + ) + : L1GatewayRouter__factory.createInterface().encodeFunctionData( + 'setGateways(address[],address[],uint256,uint256,uint256)', + [ + [l1UsdcAddress], + [l1UsdcGatewayAddress], + maxGas, + gasPriceBid, + maxSubmissionCost, + ] + ) + + if (!process.env['ROLLUP_OWNER_KEY']) { + // prepare multisig transaction(s) + + const txs = [] + if (isFeeToken) { + // prepare TX to transfer fee amount to upgrade executor + const feeTokenContract = IERC20__factory.connect( + await _getFeeToken(inbox, parentProvider), + parentProvider + ) + const feeTransferData = feeTokenContract.interface.encodeFunctionData( + 'transfer', + [upgradeExecutor.address, totalFee] + ) + txs.push({ + to: feeTokenContract.address, + value: BigNumber.from(0).toString(), + data: feeTransferData, + }) + + // prepare TX to approve router to spend the fee token + const approveData = feeTokenContract.interface.encodeFunctionData( + 'approve', + [l1RouterAddress, totalFee] + ) + txs.push({ + to: upgradeExecutor.address, + value: BigNumber.from(0).toString(), + data: approveData, + }) + } + + const upgExecutorData = upgradeExecutor.interface.encodeFunctionData( + 'executeCall', + [l1Router.address, registrationCalldata] + ) + const to = upgradeExecutor.address + + // store the multisig transaction to file + txs.push({ + to, + value: isFeeToken ? BigNumber.from(0).toString() : totalFee.toString(), + data: upgExecutorData, + }) + fs.writeFileSync(REGISTRATION_TX_FILE, JSON.stringify(txs)) + } else { + // load rollup owner (account with executor rights on the upgrade executor) + const rollupOwnerKey = process.env['ROLLUP_OWNER_KEY'] as string + const rollupOwner = new ethers.Wallet(rollupOwnerKey, parentProvider) + + if (isFeeToken) { + // transfer the fee amount to upgrade executor + const feeToken = await _getFeeToken(inbox, parentProvider) + const feeTokenContract = IERC20__factory.connect(feeToken, rollupOwner) + await ( + await feeTokenContract + .connect(rollupOwner) + .transfer(upgradeExecutor.address, totalFee) + ).wait() + + // approve router to spend the fee token + await ( + await upgradeExecutor + .connect(rollupOwner) + .executeCall( + feeToken, + feeTokenContract.interface.encodeFunctionData('approve', [ + l1RouterAddress, + totalFee, + ]) + ) + ).wait() + } + + // execute the registration + const gwRegistrationTx = await upgradeExecutor + .connect(rollupOwner) + .executeCall(l1Router.address, registrationCalldata, { + value: isFeeToken ? BigNumber.from(0) : totalFee, + }) + await _waitOnL2Msg(gwRegistrationTx, childProvider) + } +} + +/** + * Master minter (this script set it to deployer) adds minter role to L2 gateway + * with max allowance. + */ +async function _addMinterRoleToL2Gateway( + l2UsdcGateway: L2USDCGateway, + masterMinterOwner: Wallet, + masterMinter: Contract +) { + await ( + await masterMinter['configureController(address,address)']( + masterMinterOwner.address, + l2UsdcGateway.address + ) + ).wait() + + await ( + await masterMinter['configureMinter(uint256)'](ethers.constants.MaxUint256) + ).wait() +} + +/** + * Check if owner is UpgardeExecutor by polling ADMIN_ROLE() and EXECUTOR_ROLE() + */ +async function _isUpgradeExecutor( + routerOwnerAddress: string, + provider: Provider +): Promise { + const upgExecutor = UpgradeExecutor__factory.connect( + routerOwnerAddress, + provider + ) + try { + await upgExecutor.ADMIN_ROLE() + await upgExecutor.EXECUTOR_ROLE() + } catch { + return false + } + + return true +} + +/** + * Wait for L1->L2 message to be redeemed + */ +async function _waitOnL2Msg(tx: ContractTransaction, childProvider: Provider) { + const retryableReceipt = await tx.wait() + const l1TxReceipt = new L1TransactionReceipt(retryableReceipt) + const messages = await l1TxReceipt.getL1ToL2Messages(childProvider) + + // 1 msg expected + const messageResult = await messages[0].waitForStatus() + const status = messageResult.status + + if (status != L1ToL2MessageStatus.REDEEMED) { + throw new Error('L1->L2 message not redeemed') + } +} + +/** + * Register L1 and L2 networks in the SDK + * @param l1Provider + * @param l2Provider + * @param inboxAddress + * @returns + */ +async function _registerNetworks( + l1Provider: Provider, + l2Provider: Provider, + inboxAddress: string +): Promise<{ + l1Network: L1Network + l2Network: Omit +}> { + const l1NetworkInfo = await l1Provider.getNetwork() + const l2NetworkInfo = await l2Provider.getNetwork() + + const l1Network: L1Network = { + blockTime: 10, + chainID: l1NetworkInfo.chainId, + explorerUrl: '', + isCustom: true, + name: l1NetworkInfo.name, + partnerChainIDs: [l2NetworkInfo.chainId], + isArbitrum: false, + } + + const rollupAddress = await IBridge__factory.connect( + await IInboxBase__factory.connect(inboxAddress, l1Provider).bridge(), + l1Provider + ).rollup() + const rollup = RollupAdminLogic__factory.connect(rollupAddress, l1Provider) + const l2Network: L2Network = { + blockTime: 10, + partnerChainIDs: [], + chainID: l2NetworkInfo.chainId, + confirmPeriodBlocks: (await rollup.confirmPeriodBlocks()).toNumber(), + ethBridge: { + bridge: await rollup.bridge(), + inbox: await rollup.inbox(), + outbox: await rollup.outbox(), + rollup: rollup.address, + sequencerInbox: await rollup.sequencerInbox(), + }, + explorerUrl: '', + isArbitrum: true, + isCustom: true, + name: 'OrbitChain', + partnerChainID: l1NetworkInfo.chainId, + retryableLifetimeSeconds: 7 * 24 * 60 * 60, + nitroGenesisBlock: 0, + nitroGenesisL1Block: 0, + depositTimeout: 900000, + tokenBridge: { + l1CustomGateway: '', + l1ERC20Gateway: '', + l1GatewayRouter: '', + l1MultiCall: '', + l1ProxyAdmin: '', + l1Weth: '', + l1WethGateway: '', + l2CustomGateway: '', + l2ERC20Gateway: '', + l2GatewayRouter: '', + l2Multicall: '', + l2ProxyAdmin: '', + l2Weth: '', + l2WethGateway: '', + }, + } + + // register - needed for retryables + addCustomNetwork({ + customL1Network: l1Network, + customL2Network: l2Network, + }) + + return { + l1Network, + l2Network, + } +} + +/** + * Fetch fee token if it exists or return zero address + */ +async function _getFeeToken( + inbox: string, + provider: Provider +): Promise { + const bridge = await IInboxBase__factory.connect(inbox, provider).bridge() + + let feeToken = ethers.constants.AddressZero + + try { + feeToken = await IERC20Bridge__factory.connect( + bridge, + provider + ).nativeToken() + } catch { + // ignore + } + + return feeToken +} + +/** + * Check if all required env vars are set + */ +function _checkEnvVars() { + const requiredEnvVars = [ + 'PARENT_RPC', + 'PARENT_DEPLOYER_KEY', + 'CHILD_RPC', + 'CHILD_DEPLOYER_KEY', + 'L1_ROUTER', + 'L2_ROUTER', + 'INBOX', + 'L1_USDC', + ] + + for (const envVar of requiredEnvVars) { + if (!process.env[envVar]) { + throw new Error(`Missing env var ${envVar}`) + } + } +} + +async function _getPrescaledAmount( + nativeTokenAddress: string, + provider: Provider, + amount: BigNumber +): Promise { + const nativeToken = ERC20__factory.connect(nativeTokenAddress, provider) + const decimals = BigNumber.from(await nativeToken.decimals()) + if (decimals.lt(BigNumber.from(18))) { + const scalingFactor = BigNumber.from(10).pow( + BigNumber.from(18).sub(decimals) + ) + let prescaledAmount = amount.div(scalingFactor) + // round up if needed + if (prescaledAmount.mul(scalingFactor).lt(amount)) { + prescaledAmount = prescaledAmount.add(BigNumber.from(1)) + } + return prescaledAmount + } else if (decimals.gt(BigNumber.from(18))) { + return amount.mul(BigNumber.from(10).pow(decimals.sub(BigNumber.from(18)))) + } + + return amount +} diff --git a/scripts/usdc-bridge-deployment/env.example b/scripts/usdc-bridge-deployment/env.example new file mode 100644 index 0000000000..c6eefe9805 --- /dev/null +++ b/scripts/usdc-bridge-deployment/env.example @@ -0,0 +1,10 @@ +PARENT_RPC= +PARENT_DEPLOYER_KEY= +CHILD_RPC= +CHILD_DEPLOYER_KEY= +L1_ROUTER= +L2_ROUTER= +INBOX= +L1_USDC= +## OPTIONAL arg. If set, script will register the gateway, otherwise it will store TX payload in a file +ROLLUP_OWNER_KEY= \ No newline at end of file diff --git a/slither.db.json b/slither.db.json index 576dcba582..8f135eedfb 100644 --- a/slither.db.json +++ b/slither.db.json @@ -1 +1 @@ -[{"elements": [{"type": "function", "name": "outboundEscrowTransfer", "source_mapping": {"start": 11053, "length": 592, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ArbitrumGateway", "source_mapping": {"start": 1279, "length": 14336, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404], "starting_column": 1, "ending_column": 2}}, "signature": "outboundEscrowTransfer(address,address,uint256)"}}, {"type": "node", "name": "IERC20(_l1Token).safeTransferFrom(_from,address(this),_amount)", "source_mapping": {"start": 11459, "length": 64, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [301], "starting_column": 9, "ending_column": 73}, "type_specific_fields": {"parent": {"type": "function", "name": "outboundEscrowTransfer", "source_mapping": {"start": 11053, "length": 592, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ArbitrumGateway", "source_mapping": {"start": 1279, "length": 14336, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404], "starting_column": 1, "ending_column": 2}}, "signature": "outboundEscrowTransfer(address,address,uint256)"}}}}], "description": "L1ArbitrumGateway.outboundEscrowTransfer(address,address,uint256) (contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#293-304) uses arbitrary from in transferFrom: IERC20(_l1Token).safeTransferFrom(_from,address(this),_amount) (contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#301)\n", "markdown": "[L1ArbitrumGateway.outboundEscrowTransfer(address,address,uint256)](contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#L293-L304) uses arbitrary from in transferFrom: [IERC20(_l1Token).safeTransferFrom(_from,address(this),_amount)](contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#L301)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#L293-L304", "id": "7f2693a46b04c9b469a640c442acfb2aaa3e814506fef81efed08031db2d23bd", "check": "arbitrary-send-erc20", "impact": "High", "confidence": "High"}, {"elements": [{"type": "function", "name": "inboundEscrowTransfer", "source_mapping": {"start": 2818, "length": 266, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "is_dependency": false, "lines": [80, 81, 82, 83, 84, 85, 86, 87], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2WethGateway", "source_mapping": {"start": 864, "length": 2787, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107], "starting_column": 1, "ending_column": 2}}, "signature": "inboundEscrowTransfer(address,address,uint256)"}}, {"type": "node", "name": "IWETH9(_l2TokenAddress).deposit{value: _amount}()", "source_mapping": {"start": 2964, "length": 51, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "is_dependency": false, "lines": [85], "starting_column": 9, "ending_column": 60}, "type_specific_fields": {"parent": {"type": "function", "name": "inboundEscrowTransfer", "source_mapping": {"start": 2818, "length": 266, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "is_dependency": false, "lines": [80, 81, 82, 83, 84, 85, 86, 87], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2WethGateway", "source_mapping": {"start": 864, "length": 2787, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107], "starting_column": 1, "ending_column": 2}}, "signature": "inboundEscrowTransfer(address,address,uint256)"}}}}], "description": "L2WethGateway.inboundEscrowTransfer(address,address,uint256) (contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol#80-87) sends eth to arbitrary user\n\tDangerous calls:\n\t- IWETH9(_l2TokenAddress).deposit{value: _amount}() (contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol#85)\n", "markdown": "[L2WethGateway.inboundEscrowTransfer(address,address,uint256)](contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol#L80-L87) sends eth to arbitrary user\n\tDangerous calls:\n\t- [IWETH9(_l2TokenAddress).deposit{value: _amount}()](contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol#L85)\n", "first_markdown_element": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol#L80-L87", "id": "e2c734fd5c5ec43d4faaa9a093395e2556c3b429c34215a26107de1a4271f405", "check": "arbitrary-send-eth", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_sendRetryableToCreateContracts", "source_mapping": {"start": 16693, "length": 689, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableToCreateContracts(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,L2DeploymentAddresses,address,address)"}}, {"type": "node", "name": "retryableSender.sendRetryable{value: 0}(retryableParams,l2TemplateAddress,l1Deployment,l2Deployment.standardGateway,l2RollupOwner,msg.sender,upgradeExecutor)", "source_mapping": {"start": 17027, "length": 348, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418], "starting_column": 9, "ending_column": 10}, "type_specific_fields": {"parent": {"type": "function", "name": "_sendRetryableToCreateContracts", "source_mapping": {"start": 16693, "length": 689, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableToCreateContracts(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,L2DeploymentAddresses,address,address)"}}}}, {"type": "node", "name": "retryableSender.sendRetryable{value: address(this).balance}(retryableParams,l2TemplateAddress,l1Deployment,l2Deployment.standardGateway,l2RollupOwner,msg.sender,upgradeExecutor)", "source_mapping": {"start": 17027, "length": 348, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418], "starting_column": 9, "ending_column": 10}, "type_specific_fields": {"parent": {"type": "function", "name": "_sendRetryableToCreateContracts", "source_mapping": {"start": 16693, "length": 689, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableToCreateContracts(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,L2DeploymentAddresses,address,address)"}}}}], "description": "L1AtomicTokenBridgeCreator._sendRetryableToCreateContracts(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,L2DeploymentAddresses,address,address) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#400-419) sends eth to arbitrary user\n\tDangerous calls:\n\t- retryableSender.sendRetryable{value: 0}(retryableParams,l2TemplateAddress,l1Deployment,l2Deployment.standardGateway,l2RollupOwner,msg.sender,upgradeExecutor) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#408-418)\n\t- retryableSender.sendRetryable{value: address(this).balance}(retryableParams,l2TemplateAddress,l1Deployment,l2Deployment.standardGateway,l2RollupOwner,msg.sender,upgradeExecutor) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#408-418)\n", "markdown": "[L1AtomicTokenBridgeCreator._sendRetryableToCreateContracts(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,L2DeploymentAddresses,address,address)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L400-L419) sends eth to arbitrary user\n\tDangerous calls:\n\t- [retryableSender.sendRetryable{value: 0}(retryableParams,l2TemplateAddress,l1Deployment,l2Deployment.standardGateway,l2RollupOwner,msg.sender,upgradeExecutor)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L408-L418)\n\t- [retryableSender.sendRetryable{value: address(this).balance}(retryableParams,l2TemplateAddress,l1Deployment,l2Deployment.standardGateway,l2RollupOwner,msg.sender,upgradeExecutor)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L408-L418)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L400-L419", "id": "84a1b3de438b5383716ee1c6461a8a33564d9e9909292e29f6920c3dde7db801", "check": "arbitrary-send-eth", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_deployL2Factory", "source_mapping": {"start": 18302, "length": 1541, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_deployL2Factory(address,uint256,address)"}}, {"type": "node", "name": "IInbox(inbox).createRetryableTicket{value: retryableFee_scope_0}(address(0),0,maxSubmissionCost,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,deploymentData)", "source_mapping": {"start": 19509, "length": 317, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [474, 475, 476, 477, 478, 479, 480, 481, 482, 483], "starting_column": 13, "ending_column": 14}, "type_specific_fields": {"parent": {"type": "function", "name": "_deployL2Factory", "source_mapping": {"start": 18302, "length": 1541, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_deployL2Factory(address,uint256,address)"}}}}], "description": "L1AtomicTokenBridgeCreator._deployL2Factory(address,uint256,address) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#447-485) sends eth to arbitrary user\n\tDangerous calls:\n\t- IInbox(inbox).createRetryableTicket{value: retryableFee_scope_0}(address(0),0,maxSubmissionCost,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,deploymentData) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#474-483)\n", "markdown": "[L1AtomicTokenBridgeCreator._deployL2Factory(address,uint256,address)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L447-L485) sends eth to arbitrary user\n\tDangerous calls:\n\t- [IInbox(inbox).createRetryableTicket{value: retryableFee_scope_0}(address(0),0,maxSubmissionCost,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,deploymentData)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L474-L483)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L447-L485", "id": "99184e5a886f6131fdcb8318889a0655a41bf41eb6069c01f0099a0212556371", "check": "arbitrary-send-eth", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_sendRetryableUsingEth", "source_mapping": {"start": 3140, "length": 1810, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address)"}}, {"type": "node", "name": "(success,None) = deployer.call{value: address(this).balance}()", "source_mapping": {"start": 4804, "length": 65, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [118], "starting_column": 9, "ending_column": 74}, "type_specific_fields": {"parent": {"type": "function", "name": "_sendRetryableUsingEth", "source_mapping": {"start": 3140, "length": 1810, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address)"}}}}], "description": "L1TokenBridgeRetryableSender._sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#77-120) sends eth to arbitrary user\n\tDangerous calls:\n\t- (success,None) = deployer.call{value: address(this).balance}() (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#118)\n", "markdown": "[L1TokenBridgeRetryableSender._sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L77-L120) sends eth to arbitrary user\n\tDangerous calls:\n\t- [(success,None) = deployer.call{value: address(this).balance}()](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L118)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L77-L120", "id": "04b7713760c9cd5b98aaa53a7e551c516febef4ad6844a984d8a91a36843bb5e", "check": "arbitrary-send-eth", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_createRetryableUsingEth", "source_mapping": {"start": 6082, "length": 557, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_createRetryableUsingEth(RetryableParams,uint256,uint256,bytes)"}}, {"type": "node", "name": "IInbox(retryableParams.inbox).createRetryableTicket{value: value}(retryableParams.target,0,maxSubmissionCost,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,data)", "source_mapping": {"start": 6276, "length": 356, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [162, 163, 164, 165, 166, 167, 168, 169, 170, 171], "starting_column": 9, "ending_column": 10}, "type_specific_fields": {"parent": {"type": "function", "name": "_createRetryableUsingEth", "source_mapping": {"start": 6082, "length": 557, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_createRetryableUsingEth(RetryableParams,uint256,uint256,bytes)"}}}}], "description": "L1TokenBridgeRetryableSender._createRetryableUsingEth(RetryableParams,uint256,uint256,bytes) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#156-172) sends eth to arbitrary user\n\tDangerous calls:\n\t- IInbox(retryableParams.inbox).createRetryableTicket{value: value}(retryableParams.target,0,maxSubmissionCost,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,data) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#162-171)\n", "markdown": "[L1TokenBridgeRetryableSender._createRetryableUsingEth(RetryableParams,uint256,uint256,bytes)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L156-L172) sends eth to arbitrary user\n\tDangerous calls:\n\t- [IInbox(retryableParams.inbox).createRetryableTicket{value: value}(retryableParams.target,0,maxSubmissionCost,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,data)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L162-L171)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L156-L172", "id": "a7688c5005162ad9a035feab8e6c4c7161c854dec1f75d2422d647ef3ad2bfa7", "check": "arbitrary-send-eth", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "inboundEscrowTransfer", "source_mapping": {"start": 2941, "length": 245, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "is_dependency": false, "lines": [88, 89, 90, 91, 92, 93, 94, 95], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1WethGateway", "source_mapping": {"start": 965, "length": 3233, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "is_dependency": false, "lines": [28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130], "starting_column": 1, "ending_column": 2}}, "signature": "inboundEscrowTransfer(address,address,uint256)"}}, {"type": "node", "name": "IWETH9(_l1Token).deposit{value: _amount}()", "source_mapping": {"start": 3080, "length": 44, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "is_dependency": false, "lines": [93], "starting_column": 9, "ending_column": 53}, "type_specific_fields": {"parent": {"type": "function", "name": "inboundEscrowTransfer", "source_mapping": {"start": 2941, "length": 245, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "is_dependency": false, "lines": [88, 89, 90, 91, 92, 93, 94, 95], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1WethGateway", "source_mapping": {"start": 965, "length": 3233, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "is_dependency": false, "lines": [28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130], "starting_column": 1, "ending_column": 2}}, "signature": "inboundEscrowTransfer(address,address,uint256)"}}}}], "description": "L1WethGateway.inboundEscrowTransfer(address,address,uint256) (contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol#88-95) sends eth to arbitrary user\n\tDangerous calls:\n\t- IWETH9(_l1Token).deposit{value: _amount}() (contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol#93)\n", "markdown": "[L1WethGateway.inboundEscrowTransfer(address,address,uint256)](contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol#L88-L95) sends eth to arbitrary user\n\tDangerous calls:\n\t- [IWETH9(_l1Token).deposit{value: _amount}()](contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol#L93)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol#L88-L95", "id": "aefde4912f3446b807349549a2c0405d67afd0d48c7f40e4f14c642fc6454318", "check": "arbitrary-send-eth", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "redirectedExits", "source_mapping": {"start": 1128, "length": 51, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "is_dependency": false, "lines": [42], "starting_column": 5, "ending_column": 56}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ArbitrumExtendedGateway", "source_mapping": {"start": 927, "length": 4270, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "is_dependency": false, "lines": [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140], "starting_column": 1, "ending_column": 2}}}}, {"type": "function", "name": "getExternalCall", "source_mapping": {"start": 3628, "length": 925, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "is_dependency": false, "lines": [103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ArbitrumExtendedGateway", "source_mapping": {"start": 927, "length": 4270, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "is_dependency": false, "lines": [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140], "starting_column": 1, "ending_column": 2}}, "signature": "getExternalCall(uint256,address,bytes)"}}], "description": "L1ArbitrumExtendedGateway.redirectedExits (contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol#42) is never initialized. It is used in:\n\t- L1ArbitrumExtendedGateway.getExternalCall(uint256,address,bytes) (contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol#103-120)\n", "markdown": "[L1ArbitrumExtendedGateway.redirectedExits](contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol#L42) is never initialized. It is used in:\n\t- [L1ArbitrumExtendedGateway.getExternalCall(uint256,address,bytes)](contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol#L103-L120)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol#L42", "id": "e5aa1893c702d02a90473a1c603e113adcc2f5f0696cde71aac9ae09574067bf", "check": "uninitialized-state", "impact": "High", "confidence": "High"}, {"elements": [{"type": "function", "name": "_getScaledAmount", "source_mapping": {"start": 24831, "length": 559, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_getScaledAmount(address,uint256)"}}, {"type": "node", "name": "scaledAmount = amount / (10 ** (18 - decimals))", "source_mapping": {"start": 25086, "length": 55, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [610], "starting_column": 13, "ending_column": 68}, "type_specific_fields": {"parent": {"type": "function", "name": "_getScaledAmount", "source_mapping": {"start": 24831, "length": 559, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_getScaledAmount(address,uint256)"}}}}, {"type": "node", "name": "scaledAmount * (10 ** (18 - decimals)) < amount", "source_mapping": {"start": 25196, "length": 47, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [612], "starting_column": 17, "ending_column": 64}, "type_specific_fields": {"parent": {"type": "function", "name": "_getScaledAmount", "source_mapping": {"start": 24831, "length": 559, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_getScaledAmount(address,uint256)"}}}}], "description": "L1AtomicTokenBridgeCreator._getScaledAmount(address,uint256) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#604-618) performs a multiplication on the result of a division:\n\t- scaledAmount = amount / (10 ** (18 - decimals)) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#610)\n\t- scaledAmount * (10 ** (18 - decimals)) < amount (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#612)\n", "markdown": "[L1AtomicTokenBridgeCreator._getScaledAmount(address,uint256)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L604-L618) performs a multiplication on the result of a division:\n\t- [scaledAmount = amount / (10 ** (18 - decimals))](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L610)\n\t- [scaledAmount * (10 ** (18 - decimals)) < amount](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L612)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L604-L618", "id": "a2bb622fdc1256a6305ef07732ea9e8f22f715757cc69e14e9979282ee2123ef", "check": "divide-before-multiply", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "node", "name": "_deployL2Factory(inbox,gasPriceBid,feeToken)", "source_mapping": {"start": 14562, "length": 46, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [342], "starting_column": 9, "ending_column": 55}, "type_specific_fields": {"parent": {"type": "function", "name": "createTokenBridge", "source_mapping": {"start": 8217, "length": 8470, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "createTokenBridge(address,address,uint256,uint256)"}}}}, {"type": "node", "name": "_deployL2Factory(inbox,gasPriceBid,feeToken)", "source_mapping": {"start": 14562, "length": 46, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [342], "starting_column": 9, "ending_column": 55}, "type_specific_fields": {"parent": {"type": "function", "name": "createTokenBridge", "source_mapping": {"start": 8217, "length": 8470, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "createTokenBridge(address,address,uint256,uint256)"}}}}], "description": "Multiple retryable tickets created in the same function:\n\t -_deployL2Factory(inbox,gasPriceBid,feeToken) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#342)\n\t -_deployL2Factory(inbox,gasPriceBid,feeToken) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#342)\n", "markdown": "Multiple retryable tickets created in the same function:\n\t -[_deployL2Factory(inbox,gasPriceBid,feeToken)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L342)\n\t -[_deployL2Factory(inbox,gasPriceBid,feeToken)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L342)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L342", "id": "a529625c2877a63d7b2dbe920fcdb59daa32aacb3dbb402906376a5e3ddba6e7", "check": "out-of-order-retryable", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "node", "name": "_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data)", "source_mapping": {"start": 4512, "length": 82, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [113], "starting_column": 9, "ending_column": 91}, "type_specific_fields": {"parent": {"type": "function", "name": "_sendRetryableUsingEth", "source_mapping": {"start": 3140, "length": 1810, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address)"}}}}, {"type": "node", "name": "_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data)", "source_mapping": {"start": 4512, "length": 82, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [113], "starting_column": 9, "ending_column": 91}, "type_specific_fields": {"parent": {"type": "function", "name": "_sendRetryableUsingEth", "source_mapping": {"start": 3140, "length": 1810, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address)"}}}}], "description": "Multiple retryable tickets created in the same function:\n\t -_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#113)\n\t -_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#113)\n", "markdown": "Multiple retryable tickets created in the same function:\n\t -[_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L113)\n\t -[_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L113)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L113", "id": "17648cf433b86bf06bcab3f179d37fe19e73adff495e0e9485ce4b5d2d22a91b", "check": "out-of-order-retryable", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "l2Deployment", "source_mapping": {"start": 9580, "length": 41, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [224], "starting_column": 9, "ending_column": 50}, "type_specific_fields": {"parent": {"type": "function", "name": "createTokenBridge", "source_mapping": {"start": 8217, "length": 8470, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "createTokenBridge(address,address,uint256,uint256)"}}}}], "description": "L1AtomicTokenBridgeCreator.createTokenBridge(address,address,uint256,uint256).l2Deployment (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#224) is a local variable never initialized\n", "markdown": "[L1AtomicTokenBridgeCreator.createTokenBridge(address,address,uint256,uint256).l2Deployment](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L224) is a local variable never initialized\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L224", "id": "9bfb8ca665ae98867b761c889e2c325d50e1cb30307188f74f012df830627e2b", "check": "uninitialized-local", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "l2NewDefaultGateway", "source_mapping": {"start": 2756, "length": 27, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "is_dependency": false, "lines": [92], "starting_column": 9, "ending_column": 36}, "type_specific_fields": {"parent": {"type": "function", "name": "_setDefaultGateway", "source_mapping": {"start": 2425, "length": 1071, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "is_dependency": false, "lines": [81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1GatewayRouter", "source_mapping": {"start": 1254, "length": 11109, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "is_dependency": false, "lines": [35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354], "starting_column": 1, "ending_column": 2}}, "signature": "_setDefaultGateway(address,uint256,uint256,uint256,uint256)"}}}}], "description": "L1GatewayRouter._setDefaultGateway(address,uint256,uint256,uint256,uint256).l2NewDefaultGateway (contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol#92) is a local variable never initialized\n", "markdown": "[L1GatewayRouter._setDefaultGateway(address,uint256,uint256,uint256,uint256).l2NewDefaultGateway](contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol#L92) is a local variable never initialized\n", "first_markdown_element": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol#L92", "id": "8557712f770f31a8c2dbfa8451859919fe91c55860d5c13d31210fc167b6085e", "check": "uninitialized-local", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "shouldWithdraw", "source_mapping": {"start": 9380, "length": 19, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol", "is_dependency": false, "lines": [263], "starting_column": 13, "ending_column": 32}, "type_specific_fields": {"parent": {"type": "function", "name": "finalizeInboundTransfer", "source_mapping": {"start": 8148, "length": 2321, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol", "is_dependency": false, "lines": [227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2ArbitrumGateway", "source_mapping": {"start": 1103, "length": 9658, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol", "is_dependency": false, "lines": [35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299], "starting_column": 1, "ending_column": 2}}, "signature": "finalizeInboundTransfer(address,address,address,uint256,bytes)"}}}}], "description": "L2ArbitrumGateway.finalizeInboundTransfer(address,address,address,uint256,bytes).shouldWithdraw (contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol#263) is a local variable never initialized\n", "markdown": "[L2ArbitrumGateway.finalizeInboundTransfer(address,address,address,uint256,bytes).shouldWithdraw](contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol#L263) is a local variable never initialized\n", "first_markdown_element": "contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol#L263", "id": "99efcf80cf8863b2ea366b5c3a40419d4d30f7aa6912ddfcfc6869d533f387f9", "check": "uninitialized-local", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "l1Deployment", "source_mapping": {"start": 9529, "length": 41, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [223], "starting_column": 9, "ending_column": 50}, "type_specific_fields": {"parent": {"type": "function", "name": "createTokenBridge", "source_mapping": {"start": 8217, "length": 8470, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "createTokenBridge(address,address,uint256,uint256)"}}}}], "description": "L1AtomicTokenBridgeCreator.createTokenBridge(address,address,uint256,uint256).l1Deployment (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#223) is a local variable never initialized\n", "markdown": "[L1AtomicTokenBridgeCreator.createTokenBridge(address,address,uint256,uint256).l1Deployment](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L223) is a local variable never initialized\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L223", "id": "83541fa7c678a7dc42b6a8c5709120d6d76a9a51c8ccf8c6cf6e984776341180", "check": "uninitialized-local", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "deployL2Contracts", "source_mapping": {"start": 1836, "length": 2106, "filename_relative": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_short": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "is_dependency": false, "lines": [35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2AtomicTokenBridgeFactory", "source_mapping": {"start": 1325, "length": 10350, "filename_relative": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_short": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284], "starting_column": 1, "ending_column": 2}}, "signature": "deployL2Contracts(L2RuntimeCode,address,address,address,address,address,address,address,address)"}}, {"type": "node", "name": "Create2.deploy(0,_getL2Salt(OrbitSalts.L2_MULTICALL),CreationCodeHelper.getCreationCodeFor(l2Code.multicall))", "source_mapping": {"start": 3658, "length": 157, "filename_relative": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_short": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "is_dependency": false, "lines": [78, 79, 80, 81, 82], "starting_column": 9, "ending_column": 10}, "type_specific_fields": {"parent": {"type": "function", "name": "deployL2Contracts", "source_mapping": {"start": 1836, "length": 2106, "filename_relative": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_short": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "is_dependency": false, "lines": [35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2AtomicTokenBridgeFactory", "source_mapping": {"start": 1325, "length": 10350, "filename_relative": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_short": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284], "starting_column": 1, "ending_column": 2}}, "signature": "deployL2Contracts(L2RuntimeCode,address,address,address,address,address,address,address,address)"}}}}], "description": "L2AtomicTokenBridgeFactory.deployL2Contracts(L2RuntimeCode,address,address,address,address,address,address,address,address) (contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol#35-86) ignores return value by Create2.deploy(0,_getL2Salt(OrbitSalts.L2_MULTICALL),CreationCodeHelper.getCreationCodeFor(l2Code.multicall)) (contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol#78-82)\n", "markdown": "[L2AtomicTokenBridgeFactory.deployL2Contracts(L2RuntimeCode,address,address,address,address,address,address,address,address)](contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol#L35-L86) ignores return value by [Create2.deploy(0,_getL2Salt(OrbitSalts.L2_MULTICALL),CreationCodeHelper.getCreationCodeFor(l2Code.multicall))](contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol#L78-L82)\n", "first_markdown_element": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol#L35-L86", "id": "2956ed76e7f9c4953ba1242f2735d68b34ea04746ec3353fe026ad5948aa4de9", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_deployL2Factory", "source_mapping": {"start": 18302, "length": 1541, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_deployL2Factory(address,uint256,address)"}}, {"type": "node", "name": "IERC20Inbox(inbox).createRetryableTicket(address(0),0,0,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,scaledRetryableFee,deploymentData)", "source_mapping": {"start": 18926, "length": 321, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468], "starting_column": 13, "ending_column": 14}, "type_specific_fields": {"parent": {"type": "function", "name": "_deployL2Factory", "source_mapping": {"start": 18302, "length": 1541, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_deployL2Factory(address,uint256,address)"}}}}], "description": "L1AtomicTokenBridgeCreator._deployL2Factory(address,uint256,address) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#447-485) ignores return value by IERC20Inbox(inbox).createRetryableTicket(address(0),0,0,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,scaledRetryableFee,deploymentData) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#458-468)\n", "markdown": "[L1AtomicTokenBridgeCreator._deployL2Factory(address,uint256,address)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L447-L485) ignores return value by [IERC20Inbox(inbox).createRetryableTicket(address(0),0,0,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,scaledRetryableFee,deploymentData)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L458-L468)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L447-L485", "id": "dc6f44871a7669ec4f8efc4b8484c6188fb3d717556f325671cf5d2fde4a1b09", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_deployL2Factory", "source_mapping": {"start": 18302, "length": 1541, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_deployL2Factory(address,uint256,address)"}}, {"type": "node", "name": "IInbox(inbox).createRetryableTicket{value: retryableFee_scope_0}(address(0),0,maxSubmissionCost,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,deploymentData)", "source_mapping": {"start": 19509, "length": 317, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [474, 475, 476, 477, 478, 479, 480, 481, 482, 483], "starting_column": 13, "ending_column": 14}, "type_specific_fields": {"parent": {"type": "function", "name": "_deployL2Factory", "source_mapping": {"start": 18302, "length": 1541, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_deployL2Factory(address,uint256,address)"}}}}], "description": "L1AtomicTokenBridgeCreator._deployL2Factory(address,uint256,address) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#447-485) ignores return value by IInbox(inbox).createRetryableTicket{value: retryableFee_scope_0}(address(0),0,maxSubmissionCost,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,deploymentData) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#474-483)\n", "markdown": "[L1AtomicTokenBridgeCreator._deployL2Factory(address,uint256,address)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L447-L485) ignores return value by [IInbox(inbox).createRetryableTicket{value: retryableFee_scope_0}(address(0),0,maxSubmissionCost,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,deploymentData)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L474-L483)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L447-L485", "id": "e020b241fb03d0676863525627c28d172830b0205edf229997b005753861a0e9", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_createRetryableUsingEth", "source_mapping": {"start": 6082, "length": 557, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_createRetryableUsingEth(RetryableParams,uint256,uint256,bytes)"}}, {"type": "node", "name": "IInbox(retryableParams.inbox).createRetryableTicket{value: value}(retryableParams.target,0,maxSubmissionCost,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,data)", "source_mapping": {"start": 6276, "length": 356, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [162, 163, 164, 165, 166, 167, 168, 169, 170, 171], "starting_column": 9, "ending_column": 10}, "type_specific_fields": {"parent": {"type": "function", "name": "_createRetryableUsingEth", "source_mapping": {"start": 6082, "length": 557, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_createRetryableUsingEth(RetryableParams,uint256,uint256,bytes)"}}}}], "description": "L1TokenBridgeRetryableSender._createRetryableUsingEth(RetryableParams,uint256,uint256,bytes) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#156-172) ignores return value by IInbox(retryableParams.inbox).createRetryableTicket{value: value}(retryableParams.target,0,maxSubmissionCost,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,data) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#162-171)\n", "markdown": "[L1TokenBridgeRetryableSender._createRetryableUsingEth(RetryableParams,uint256,uint256,bytes)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L156-L172) ignores return value by [IInbox(retryableParams.inbox).createRetryableTicket{value: value}(retryableParams.target,0,maxSubmissionCost,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,data)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L162-L171)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L156-L172", "id": "f3fce683bbb88d3bc3deac571c8226af666c3cd0ba19d493a68e53fcf76039c3", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_createRetryableUsingFeeToken", "source_mapping": {"start": 6645, "length": 531, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_createRetryableUsingFeeToken(RetryableParams,bytes)"}}, {"type": "node", "name": "IERC20Inbox(retryableParams.inbox).createRetryableTicket(retryableParams.target,0,0,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,retryableParams.feeTokenTotalFeeAmount,data)", "source_mapping": {"start": 6786, "length": 383, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188], "starting_column": 9, "ending_column": 10}, "type_specific_fields": {"parent": {"type": "function", "name": "_createRetryableUsingFeeToken", "source_mapping": {"start": 6645, "length": 531, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_createRetryableUsingFeeToken(RetryableParams,bytes)"}}}}], "description": "L1TokenBridgeRetryableSender._createRetryableUsingFeeToken(RetryableParams,bytes) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#174-189) ignores return value by IERC20Inbox(retryableParams.inbox).createRetryableTicket(retryableParams.target,0,0,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,retryableParams.feeTokenTotalFeeAmount,data) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#178-188)\n", "markdown": "[L1TokenBridgeRetryableSender._createRetryableUsingFeeToken(RetryableParams,bytes)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L174-L189) ignores return value by [IERC20Inbox(retryableParams.inbox).createRetryableTicket(retryableParams.target,0,0,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,retryableParams.feeTokenTotalFeeAmount,data)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L178-L188)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L174-L189", "id": "b1f97e28632bc95bd065ae9a26c8acbdfd7cdd6155fe5910bf1567df8d76fe31", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}] \ No newline at end of file +[{"elements": [{"type": "function", "name": "outboundEscrowTransfer", "source_mapping": {"start": 11152, "length": 592, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/user/src/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ArbitrumGateway", "source_mapping": {"start": 1279, "length": 14435, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/user/src/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405], "starting_column": 1, "ending_column": 2}}, "signature": "outboundEscrowTransfer(address,address,uint256)"}}, {"type": "node", "name": "IERC20(_l1Token).safeTransferFrom(_from,address(this),_amount)", "source_mapping": {"start": 11558, "length": 64, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/user/src/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [302], "starting_column": 9, "ending_column": 73}, "type_specific_fields": {"parent": {"type": "function", "name": "outboundEscrowTransfer", "source_mapping": {"start": 11152, "length": 592, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/user/src/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ArbitrumGateway", "source_mapping": {"start": 1279, "length": 14435, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/user/src/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405], "starting_column": 1, "ending_column": 2}}, "signature": "outboundEscrowTransfer(address,address,uint256)"}}}}], "description": "L1ArbitrumGateway.outboundEscrowTransfer(address,address,uint256) (contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#294-305) uses arbitrary from in transferFrom: IERC20(_l1Token).safeTransferFrom(_from,address(this),_amount) (contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#302)\n", "markdown": "[L1ArbitrumGateway.outboundEscrowTransfer(address,address,uint256)](contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#L294-L305) uses arbitrary from in transferFrom: [IERC20(_l1Token).safeTransferFrom(_from,address(this),_amount)](contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#L302)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#L294-L305", "id": "f4868f30438c18299d3ca97a6953bb3821b2113cef0fccb26322509212561cd0", "check": "arbitrary-send-erc20", "impact": "High", "confidence": "High"}, {"elements": [{"type": "function", "name": "inboundEscrowTransfer", "source_mapping": {"start": 6147, "length": 181, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "is_dependency": false, "lines": [168, 169, 170, 171, 172, 173], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2USDCGateway", "source_mapping": {"start": 1587, "length": 6252, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "is_dependency": false, "lines": [29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216], "starting_column": 1, "ending_column": 2}}, "signature": "inboundEscrowTransfer(address,address,uint256)"}}, {"type": "node", "name": "IFiatToken(_l2Address).mint(_dest,_amount)", "source_mapping": {"start": 6278, "length": 43, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "is_dependency": false, "lines": [172], "starting_column": 9, "ending_column": 52}, "type_specific_fields": {"parent": {"type": "function", "name": "inboundEscrowTransfer", "source_mapping": {"start": 6147, "length": 181, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "is_dependency": false, "lines": [168, 169, 170, 171, 172, 173], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2USDCGateway", "source_mapping": {"start": 1587, "length": 6252, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "is_dependency": false, "lines": [29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216], "starting_column": 1, "ending_column": 2}}, "signature": "inboundEscrowTransfer(address,address,uint256)"}}}}], "description": "L2USDCGateway.inboundEscrowTransfer(address,address,uint256) (contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol#168-173) ignores return value by IFiatToken(_l2Address).mint(_dest,_amount) (contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol#172)\n", "markdown": "[L2USDCGateway.inboundEscrowTransfer(address,address,uint256)](contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol#L168-L173) ignores return value by [IFiatToken(_l2Address).mint(_dest,_amount)](contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol#L172)\n", "first_markdown_element": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol#L168-L173", "id": "e66b5e9367f98175ecac6f63c52b8f9b4423b5805d002f29ebaa548c0e806714", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "perform", "source_mapping": {"start": 169, "length": 755, "filename_relative": "contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "filename_short": "contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "RegisterUsdcGatewayAction", "source_mapping": {"start": 128, "length": 798, "filename_relative": "contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "filename_short": "contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "is_dependency": false, "lines": [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28], "starting_column": 1, "ending_column": 2}}, "signature": "perform(uint256,uint256,uint256)"}}, {"type": "node", "name": "L1GatewayRouter(router).setGateways{value: msg.value}(_token,_gateway,_maxGas,_gasPriceBid,_maxSubmissionCost)", "source_mapping": {"start": 635, "length": 136, "filename_relative": "contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "filename_short": "contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "is_dependency": false, "lines": [19, 20, 21], "starting_column": 9, "ending_column": 10}, "type_specific_fields": {"parent": {"type": "function", "name": "perform", "source_mapping": {"start": 169, "length": 755, "filename_relative": "contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "filename_short": "contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "RegisterUsdcGatewayAction", "source_mapping": {"start": 128, "length": 798, "filename_relative": "contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "filename_short": "contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol", "is_dependency": false, "lines": [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28], "starting_column": 1, "ending_column": 2}}, "signature": "perform(uint256,uint256,uint256)"}}}}], "description": "RegisterUsdcGatewayAction.perform(uint256,uint256,uint256) (contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol#7-27) ignores return value by L1GatewayRouter(router).setGateways{value: msg.value}(_token,_gateway,_maxGas,_gasPriceBid,_maxSubmissionCost) (contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol#19-21)\n", "markdown": "[RegisterUsdcGatewayAction.perform(uint256,uint256,uint256)](contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol#L7-L27) ignores return value by [L1GatewayRouter(router).setGateways{value: msg.value}(_token,_gateway,_maxGas,_gasPriceBid,_maxSubmissionCost)](contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol#L19-L21)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/RegisterUsdcGatewayAction.sol#L7-L27", "id": "cd44d30bd7ed46324a309977cb28ba80e6e75b94c03df10c5c8f5a74437d0f7c", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "outboundEscrowTransfer", "source_mapping": {"start": 11053, "length": 592, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ArbitrumGateway", "source_mapping": {"start": 1279, "length": 14336, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404], "starting_column": 1, "ending_column": 2}}, "signature": "outboundEscrowTransfer(address,address,uint256)"}}, {"type": "node", "name": "IERC20(_l1Token).safeTransferFrom(_from,address(this),_amount)", "source_mapping": {"start": 11459, "length": 64, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [301], "starting_column": 9, "ending_column": 73}, "type_specific_fields": {"parent": {"type": "function", "name": "outboundEscrowTransfer", "source_mapping": {"start": 11053, "length": 592, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ArbitrumGateway", "source_mapping": {"start": 1279, "length": 14336, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", "is_dependency": false, "lines": [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404], "starting_column": 1, "ending_column": 2}}, "signature": "outboundEscrowTransfer(address,address,uint256)"}}}}], "description": "L1ArbitrumGateway.outboundEscrowTransfer(address,address,uint256) (contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#293-304) uses arbitrary from in transferFrom: IERC20(_l1Token).safeTransferFrom(_from,address(this),_amount) (contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#301)\n", "markdown": "[L1ArbitrumGateway.outboundEscrowTransfer(address,address,uint256)](contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#L293-L304) uses arbitrary from in transferFrom: [IERC20(_l1Token).safeTransferFrom(_from,address(this),_amount)](contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#L301)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol#L293-L304", "id": "7f2693a46b04c9b469a640c442acfb2aaa3e814506fef81efed08031db2d23bd", "check": "arbitrary-send-erc20", "impact": "High", "confidence": "High"}, {"elements": [{"type": "function", "name": "inboundEscrowTransfer", "source_mapping": {"start": 2818, "length": 266, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "is_dependency": false, "lines": [80, 81, 82, 83, 84, 85, 86, 87], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2WethGateway", "source_mapping": {"start": 864, "length": 2787, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107], "starting_column": 1, "ending_column": 2}}, "signature": "inboundEscrowTransfer(address,address,uint256)"}}, {"type": "node", "name": "IWETH9(_l2TokenAddress).deposit{value: _amount}()", "source_mapping": {"start": 2964, "length": 51, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "is_dependency": false, "lines": [85], "starting_column": 9, "ending_column": 60}, "type_specific_fields": {"parent": {"type": "function", "name": "inboundEscrowTransfer", "source_mapping": {"start": 2818, "length": 266, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "is_dependency": false, "lines": [80, 81, 82, 83, 84, 85, 86, 87], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2WethGateway", "source_mapping": {"start": 864, "length": 2787, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107], "starting_column": 1, "ending_column": 2}}, "signature": "inboundEscrowTransfer(address,address,uint256)"}}}}], "description": "L2WethGateway.inboundEscrowTransfer(address,address,uint256) (contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol#80-87) sends eth to arbitrary user\n\tDangerous calls:\n\t- IWETH9(_l2TokenAddress).deposit{value: _amount}() (contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol#85)\n", "markdown": "[L2WethGateway.inboundEscrowTransfer(address,address,uint256)](contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol#L80-L87) sends eth to arbitrary user\n\tDangerous calls:\n\t- [IWETH9(_l2TokenAddress).deposit{value: _amount}()](contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol#L85)\n", "first_markdown_element": "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol#L80-L87", "id": "e2c734fd5c5ec43d4faaa9a093395e2556c3b429c34215a26107de1a4271f405", "check": "arbitrary-send-eth", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_sendRetryableToCreateContracts", "source_mapping": {"start": 16693, "length": 689, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableToCreateContracts(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,L2DeploymentAddresses,address,address)"}}, {"type": "node", "name": "retryableSender.sendRetryable{value: 0}(retryableParams,l2TemplateAddress,l1Deployment,l2Deployment.standardGateway,l2RollupOwner,msg.sender,upgradeExecutor)", "source_mapping": {"start": 17027, "length": 348, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418], "starting_column": 9, "ending_column": 10}, "type_specific_fields": {"parent": {"type": "function", "name": "_sendRetryableToCreateContracts", "source_mapping": {"start": 16693, "length": 689, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableToCreateContracts(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,L2DeploymentAddresses,address,address)"}}}}, {"type": "node", "name": "retryableSender.sendRetryable{value: address(this).balance}(retryableParams,l2TemplateAddress,l1Deployment,l2Deployment.standardGateway,l2RollupOwner,msg.sender,upgradeExecutor)", "source_mapping": {"start": 17027, "length": 348, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418], "starting_column": 9, "ending_column": 10}, "type_specific_fields": {"parent": {"type": "function", "name": "_sendRetryableToCreateContracts", "source_mapping": {"start": 16693, "length": 689, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableToCreateContracts(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,L2DeploymentAddresses,address,address)"}}}}], "description": "L1AtomicTokenBridgeCreator._sendRetryableToCreateContracts(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,L2DeploymentAddresses,address,address) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#400-419) sends eth to arbitrary user\n\tDangerous calls:\n\t- retryableSender.sendRetryable{value: 0}(retryableParams,l2TemplateAddress,l1Deployment,l2Deployment.standardGateway,l2RollupOwner,msg.sender,upgradeExecutor) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#408-418)\n\t- retryableSender.sendRetryable{value: address(this).balance}(retryableParams,l2TemplateAddress,l1Deployment,l2Deployment.standardGateway,l2RollupOwner,msg.sender,upgradeExecutor) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#408-418)\n", "markdown": "[L1AtomicTokenBridgeCreator._sendRetryableToCreateContracts(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,L2DeploymentAddresses,address,address)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L400-L419) sends eth to arbitrary user\n\tDangerous calls:\n\t- [retryableSender.sendRetryable{value: 0}(retryableParams,l2TemplateAddress,l1Deployment,l2Deployment.standardGateway,l2RollupOwner,msg.sender,upgradeExecutor)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L408-L418)\n\t- [retryableSender.sendRetryable{value: address(this).balance}(retryableParams,l2TemplateAddress,l1Deployment,l2Deployment.standardGateway,l2RollupOwner,msg.sender,upgradeExecutor)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L408-L418)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L400-L419", "id": "84a1b3de438b5383716ee1c6461a8a33564d9e9909292e29f6920c3dde7db801", "check": "arbitrary-send-eth", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_deployL2Factory", "source_mapping": {"start": 18302, "length": 1541, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_deployL2Factory(address,uint256,address)"}}, {"type": "node", "name": "IInbox(inbox).createRetryableTicket{value: retryableFee_scope_0}(address(0),0,maxSubmissionCost,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,deploymentData)", "source_mapping": {"start": 19509, "length": 317, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [474, 475, 476, 477, 478, 479, 480, 481, 482, 483], "starting_column": 13, "ending_column": 14}, "type_specific_fields": {"parent": {"type": "function", "name": "_deployL2Factory", "source_mapping": {"start": 18302, "length": 1541, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_deployL2Factory(address,uint256,address)"}}}}], "description": "L1AtomicTokenBridgeCreator._deployL2Factory(address,uint256,address) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#447-485) sends eth to arbitrary user\n\tDangerous calls:\n\t- IInbox(inbox).createRetryableTicket{value: retryableFee_scope_0}(address(0),0,maxSubmissionCost,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,deploymentData) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#474-483)\n", "markdown": "[L1AtomicTokenBridgeCreator._deployL2Factory(address,uint256,address)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L447-L485) sends eth to arbitrary user\n\tDangerous calls:\n\t- [IInbox(inbox).createRetryableTicket{value: retryableFee_scope_0}(address(0),0,maxSubmissionCost,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,deploymentData)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L474-L483)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L447-L485", "id": "99184e5a886f6131fdcb8318889a0655a41bf41eb6069c01f0099a0212556371", "check": "arbitrary-send-eth", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_sendRetryableUsingEth", "source_mapping": {"start": 3140, "length": 1810, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address)"}}, {"type": "node", "name": "(success,None) = deployer.call{value: address(this).balance}()", "source_mapping": {"start": 4804, "length": 65, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [118], "starting_column": 9, "ending_column": 74}, "type_specific_fields": {"parent": {"type": "function", "name": "_sendRetryableUsingEth", "source_mapping": {"start": 3140, "length": 1810, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address)"}}}}], "description": "L1TokenBridgeRetryableSender._sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#77-120) sends eth to arbitrary user\n\tDangerous calls:\n\t- (success,None) = deployer.call{value: address(this).balance}() (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#118)\n", "markdown": "[L1TokenBridgeRetryableSender._sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L77-L120) sends eth to arbitrary user\n\tDangerous calls:\n\t- [(success,None) = deployer.call{value: address(this).balance}()](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L118)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L77-L120", "id": "04b7713760c9cd5b98aaa53a7e551c516febef4ad6844a984d8a91a36843bb5e", "check": "arbitrary-send-eth", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_createRetryableUsingEth", "source_mapping": {"start": 6082, "length": 557, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_createRetryableUsingEth(RetryableParams,uint256,uint256,bytes)"}}, {"type": "node", "name": "IInbox(retryableParams.inbox).createRetryableTicket{value: value}(retryableParams.target,0,maxSubmissionCost,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,data)", "source_mapping": {"start": 6276, "length": 356, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [162, 163, 164, 165, 166, 167, 168, 169, 170, 171], "starting_column": 9, "ending_column": 10}, "type_specific_fields": {"parent": {"type": "function", "name": "_createRetryableUsingEth", "source_mapping": {"start": 6082, "length": 557, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_createRetryableUsingEth(RetryableParams,uint256,uint256,bytes)"}}}}], "description": "L1TokenBridgeRetryableSender._createRetryableUsingEth(RetryableParams,uint256,uint256,bytes) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#156-172) sends eth to arbitrary user\n\tDangerous calls:\n\t- IInbox(retryableParams.inbox).createRetryableTicket{value: value}(retryableParams.target,0,maxSubmissionCost,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,data) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#162-171)\n", "markdown": "[L1TokenBridgeRetryableSender._createRetryableUsingEth(RetryableParams,uint256,uint256,bytes)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L156-L172) sends eth to arbitrary user\n\tDangerous calls:\n\t- [IInbox(retryableParams.inbox).createRetryableTicket{value: value}(retryableParams.target,0,maxSubmissionCost,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,data)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L162-L171)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L156-L172", "id": "a7688c5005162ad9a035feab8e6c4c7161c854dec1f75d2422d647ef3ad2bfa7", "check": "arbitrary-send-eth", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "inboundEscrowTransfer", "source_mapping": {"start": 2941, "length": 245, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "is_dependency": false, "lines": [88, 89, 90, 91, 92, 93, 94, 95], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1WethGateway", "source_mapping": {"start": 965, "length": 3233, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "is_dependency": false, "lines": [28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130], "starting_column": 1, "ending_column": 2}}, "signature": "inboundEscrowTransfer(address,address,uint256)"}}, {"type": "node", "name": "IWETH9(_l1Token).deposit{value: _amount}()", "source_mapping": {"start": 3080, "length": 44, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "is_dependency": false, "lines": [93], "starting_column": 9, "ending_column": 53}, "type_specific_fields": {"parent": {"type": "function", "name": "inboundEscrowTransfer", "source_mapping": {"start": 2941, "length": 245, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "is_dependency": false, "lines": [88, 89, 90, 91, 92, 93, 94, 95], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1WethGateway", "source_mapping": {"start": 965, "length": 3233, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", "is_dependency": false, "lines": [28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130], "starting_column": 1, "ending_column": 2}}, "signature": "inboundEscrowTransfer(address,address,uint256)"}}}}], "description": "L1WethGateway.inboundEscrowTransfer(address,address,uint256) (contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol#88-95) sends eth to arbitrary user\n\tDangerous calls:\n\t- IWETH9(_l1Token).deposit{value: _amount}() (contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol#93)\n", "markdown": "[L1WethGateway.inboundEscrowTransfer(address,address,uint256)](contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol#L88-L95) sends eth to arbitrary user\n\tDangerous calls:\n\t- [IWETH9(_l1Token).deposit{value: _amount}()](contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol#L93)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol#L88-L95", "id": "aefde4912f3446b807349549a2c0405d67afd0d48c7f40e4f14c642fc6454318", "check": "arbitrary-send-eth", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "redirectedExits", "source_mapping": {"start": 1128, "length": 51, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "is_dependency": false, "lines": [42], "starting_column": 5, "ending_column": 56}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ArbitrumExtendedGateway", "source_mapping": {"start": 927, "length": 4270, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "is_dependency": false, "lines": [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140], "starting_column": 1, "ending_column": 2}}}}, {"type": "function", "name": "getExternalCall", "source_mapping": {"start": 3628, "length": 925, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "is_dependency": false, "lines": [103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ArbitrumExtendedGateway", "source_mapping": {"start": 927, "length": 4270, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", "is_dependency": false, "lines": [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140], "starting_column": 1, "ending_column": 2}}, "signature": "getExternalCall(uint256,address,bytes)"}}], "description": "L1ArbitrumExtendedGateway.redirectedExits (contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol#42) is never initialized. It is used in:\n\t- L1ArbitrumExtendedGateway.getExternalCall(uint256,address,bytes) (contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol#103-120)\n", "markdown": "[L1ArbitrumExtendedGateway.redirectedExits](contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol#L42) is never initialized. It is used in:\n\t- [L1ArbitrumExtendedGateway.getExternalCall(uint256,address,bytes)](contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol#L103-L120)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol#L42", "id": "e5aa1893c702d02a90473a1c603e113adcc2f5f0696cde71aac9ae09574067bf", "check": "uninitialized-state", "impact": "High", "confidence": "High"}, {"elements": [{"type": "function", "name": "_getScaledAmount", "source_mapping": {"start": 24831, "length": 559, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_getScaledAmount(address,uint256)"}}, {"type": "node", "name": "scaledAmount = amount / (10 ** (18 - decimals))", "source_mapping": {"start": 25086, "length": 55, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [610], "starting_column": 13, "ending_column": 68}, "type_specific_fields": {"parent": {"type": "function", "name": "_getScaledAmount", "source_mapping": {"start": 24831, "length": 559, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_getScaledAmount(address,uint256)"}}}}, {"type": "node", "name": "scaledAmount * (10 ** (18 - decimals)) < amount", "source_mapping": {"start": 25196, "length": 47, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [612], "starting_column": 17, "ending_column": 64}, "type_specific_fields": {"parent": {"type": "function", "name": "_getScaledAmount", "source_mapping": {"start": 24831, "length": 559, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_getScaledAmount(address,uint256)"}}}}], "description": "L1AtomicTokenBridgeCreator._getScaledAmount(address,uint256) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#604-618) performs a multiplication on the result of a division:\n\t- scaledAmount = amount / (10 ** (18 - decimals)) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#610)\n\t- scaledAmount * (10 ** (18 - decimals)) < amount (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#612)\n", "markdown": "[L1AtomicTokenBridgeCreator._getScaledAmount(address,uint256)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L604-L618) performs a multiplication on the result of a division:\n\t- [scaledAmount = amount / (10 ** (18 - decimals))](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L610)\n\t- [scaledAmount * (10 ** (18 - decimals)) < amount](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L612)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L604-L618", "id": "a2bb622fdc1256a6305ef07732ea9e8f22f715757cc69e14e9979282ee2123ef", "check": "divide-before-multiply", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "node", "name": "_deployL2Factory(inbox,gasPriceBid,feeToken)", "source_mapping": {"start": 14562, "length": 46, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [342], "starting_column": 9, "ending_column": 55}, "type_specific_fields": {"parent": {"type": "function", "name": "createTokenBridge", "source_mapping": {"start": 8217, "length": 8470, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "createTokenBridge(address,address,uint256,uint256)"}}}}, {"type": "node", "name": "_deployL2Factory(inbox,gasPriceBid,feeToken)", "source_mapping": {"start": 14562, "length": 46, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [342], "starting_column": 9, "ending_column": 55}, "type_specific_fields": {"parent": {"type": "function", "name": "createTokenBridge", "source_mapping": {"start": 8217, "length": 8470, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "createTokenBridge(address,address,uint256,uint256)"}}}}], "description": "Multiple retryable tickets created in the same function:\n\t -_deployL2Factory(inbox,gasPriceBid,feeToken) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#342)\n\t -_deployL2Factory(inbox,gasPriceBid,feeToken) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#342)\n", "markdown": "Multiple retryable tickets created in the same function:\n\t -[_deployL2Factory(inbox,gasPriceBid,feeToken)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L342)\n\t -[_deployL2Factory(inbox,gasPriceBid,feeToken)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L342)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L342", "id": "a529625c2877a63d7b2dbe920fcdb59daa32aacb3dbb402906376a5e3ddba6e7", "check": "out-of-order-retryable", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "node", "name": "_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data)", "source_mapping": {"start": 4512, "length": 82, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [113], "starting_column": 9, "ending_column": 91}, "type_specific_fields": {"parent": {"type": "function", "name": "_sendRetryableUsingEth", "source_mapping": {"start": 3140, "length": 1810, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address)"}}}}, {"type": "node", "name": "_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data)", "source_mapping": {"start": 4512, "length": 82, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [113], "starting_column": 9, "ending_column": 91}, "type_specific_fields": {"parent": {"type": "function", "name": "_sendRetryableUsingEth", "source_mapping": {"start": 3140, "length": 1810, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address)"}}}}], "description": "Multiple retryable tickets created in the same function:\n\t -_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#113)\n\t -_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#113)\n", "markdown": "Multiple retryable tickets created in the same function:\n\t -[_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L113)\n\t -[_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L113)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L113", "id": "17648cf433b86bf06bcab3f179d37fe19e73adff495e0e9485ce4b5d2d22a91b", "check": "out-of-order-retryable", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "l1Deployment", "source_mapping": {"start": 9529, "length": 41, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [223], "starting_column": 9, "ending_column": 50}, "type_specific_fields": {"parent": {"type": "function", "name": "createTokenBridge", "source_mapping": {"start": 8217, "length": 8470, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "createTokenBridge(address,address,uint256,uint256)"}}}}], "description": "L1AtomicTokenBridgeCreator.createTokenBridge(address,address,uint256,uint256).l1Deployment (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#223) is a local variable never initialized\n", "markdown": "[L1AtomicTokenBridgeCreator.createTokenBridge(address,address,uint256,uint256).l1Deployment](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L223) is a local variable never initialized\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L223", "id": "83541fa7c678a7dc42b6a8c5709120d6d76a9a51c8ccf8c6cf6e984776341180", "check": "uninitialized-local", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "l2Deployment", "source_mapping": {"start": 9580, "length": 41, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [224], "starting_column": 9, "ending_column": 50}, "type_specific_fields": {"parent": {"type": "function", "name": "createTokenBridge", "source_mapping": {"start": 8217, "length": 8470, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "createTokenBridge(address,address,uint256,uint256)"}}}}], "description": "L1AtomicTokenBridgeCreator.createTokenBridge(address,address,uint256,uint256).l2Deployment (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#224) is a local variable never initialized\n", "markdown": "[L1AtomicTokenBridgeCreator.createTokenBridge(address,address,uint256,uint256).l2Deployment](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L224) is a local variable never initialized\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L224", "id": "9bfb8ca665ae98867b761c889e2c325d50e1cb30307188f74f012df830627e2b", "check": "uninitialized-local", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "l2NewDefaultGateway", "source_mapping": {"start": 2756, "length": 27, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "is_dependency": false, "lines": [92], "starting_column": 9, "ending_column": 36}, "type_specific_fields": {"parent": {"type": "function", "name": "_setDefaultGateway", "source_mapping": {"start": 2425, "length": 1071, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "is_dependency": false, "lines": [81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1GatewayRouter", "source_mapping": {"start": 1254, "length": 11109, "filename_relative": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "filename_short": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", "is_dependency": false, "lines": [35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354], "starting_column": 1, "ending_column": 2}}, "signature": "_setDefaultGateway(address,uint256,uint256,uint256,uint256)"}}}}], "description": "L1GatewayRouter._setDefaultGateway(address,uint256,uint256,uint256,uint256).l2NewDefaultGateway (contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol#92) is a local variable never initialized\n", "markdown": "[L1GatewayRouter._setDefaultGateway(address,uint256,uint256,uint256,uint256).l2NewDefaultGateway](contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol#L92) is a local variable never initialized\n", "first_markdown_element": "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol#L92", "id": "8557712f770f31a8c2dbfa8451859919fe91c55860d5c13d31210fc167b6085e", "check": "uninitialized-local", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "deployL2Contracts", "source_mapping": {"start": 1836, "length": 2106, "filename_relative": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_short": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "is_dependency": false, "lines": [35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2AtomicTokenBridgeFactory", "source_mapping": {"start": 1325, "length": 10350, "filename_relative": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_short": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284], "starting_column": 1, "ending_column": 2}}, "signature": "deployL2Contracts(L2RuntimeCode,address,address,address,address,address,address,address,address)"}}, {"type": "node", "name": "Create2.deploy(0,_getL2Salt(OrbitSalts.L2_MULTICALL),CreationCodeHelper.getCreationCodeFor(l2Code.multicall))", "source_mapping": {"start": 3658, "length": 157, "filename_relative": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_short": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "is_dependency": false, "lines": [78, 79, 80, 81, 82], "starting_column": 9, "ending_column": 10}, "type_specific_fields": {"parent": {"type": "function", "name": "deployL2Contracts", "source_mapping": {"start": 1836, "length": 2106, "filename_relative": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_short": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "is_dependency": false, "lines": [35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2AtomicTokenBridgeFactory", "source_mapping": {"start": 1325, "length": 10350, "filename_relative": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "filename_short": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284], "starting_column": 1, "ending_column": 2}}, "signature": "deployL2Contracts(L2RuntimeCode,address,address,address,address,address,address,address,address)"}}}}], "description": "L2AtomicTokenBridgeFactory.deployL2Contracts(L2RuntimeCode,address,address,address,address,address,address,address,address) (contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol#35-86) ignores return value by Create2.deploy(0,_getL2Salt(OrbitSalts.L2_MULTICALL),CreationCodeHelper.getCreationCodeFor(l2Code.multicall)) (contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol#78-82)\n", "markdown": "[L2AtomicTokenBridgeFactory.deployL2Contracts(L2RuntimeCode,address,address,address,address,address,address,address,address)](contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol#L35-L86) ignores return value by [Create2.deploy(0,_getL2Salt(OrbitSalts.L2_MULTICALL),CreationCodeHelper.getCreationCodeFor(l2Code.multicall))](contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol#L78-L82)\n", "first_markdown_element": "contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol#L35-L86", "id": "2956ed76e7f9c4953ba1242f2735d68b34ea04746ec3353fe026ad5948aa4de9", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "inboundEscrowTransfer", "source_mapping": {"start": 5924, "length": 181, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "is_dependency": false, "lines": [165, 166, 167, 168, 169, 170], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2USDCGateway", "source_mapping": {"start": 1364, "length": 6252, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213], "starting_column": 1, "ending_column": 2}}, "signature": "inboundEscrowTransfer(address,address,uint256)"}}, {"type": "node", "name": "IFiatToken(_l2Address).mint(_dest,_amount)", "source_mapping": {"start": 6055, "length": 43, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "is_dependency": false, "lines": [169], "starting_column": 9, "ending_column": 52}, "type_specific_fields": {"parent": {"type": "function", "name": "inboundEscrowTransfer", "source_mapping": {"start": 5924, "length": 181, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "is_dependency": false, "lines": [165, 166, 167, 168, 169, 170], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2USDCGateway", "source_mapping": {"start": 1364, "length": 6252, "filename_relative": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "filename_short": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213], "starting_column": 1, "ending_column": 2}}, "signature": "inboundEscrowTransfer(address,address,uint256)"}}}}], "description": "L2USDCGateway.inboundEscrowTransfer(address,address,uint256) (contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol#165-170) ignores return value by IFiatToken(_l2Address).mint(_dest,_amount) (contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol#169)\n", "markdown": "[L2USDCGateway.inboundEscrowTransfer(address,address,uint256)](contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol#L165-L170) ignores return value by [IFiatToken(_l2Address).mint(_dest,_amount)](contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol#L169)\n", "first_markdown_element": "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol#L165-L170", "id": "b25f84626d48e5778e53022dd8067ab3aac7279a96c02a6e6d0569fc0cd1cc8a", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_deployL2Factory", "source_mapping": {"start": 18302, "length": 1541, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_deployL2Factory(address,uint256,address)"}}, {"type": "node", "name": "IERC20Inbox(inbox).createRetryableTicket(address(0),0,0,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,scaledRetryableFee,deploymentData)", "source_mapping": {"start": 18926, "length": 321, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468], "starting_column": 13, "ending_column": 14}, "type_specific_fields": {"parent": {"type": "function", "name": "_deployL2Factory", "source_mapping": {"start": 18302, "length": 1541, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_deployL2Factory(address,uint256,address)"}}}}], "description": "L1AtomicTokenBridgeCreator._deployL2Factory(address,uint256,address) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#447-485) ignores return value by IERC20Inbox(inbox).createRetryableTicket(address(0),0,0,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,scaledRetryableFee,deploymentData) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#458-468)\n", "markdown": "[L1AtomicTokenBridgeCreator._deployL2Factory(address,uint256,address)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L447-L485) ignores return value by [IERC20Inbox(inbox).createRetryableTicket(address(0),0,0,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,scaledRetryableFee,deploymentData)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L458-L468)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L447-L485", "id": "dc6f44871a7669ec4f8efc4b8484c6188fb3d717556f325671cf5d2fde4a1b09", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_deployL2Factory", "source_mapping": {"start": 18302, "length": 1541, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_deployL2Factory(address,uint256,address)"}}, {"type": "node", "name": "IInbox(inbox).createRetryableTicket{value: retryableFee_scope_0}(address(0),0,maxSubmissionCost,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,deploymentData)", "source_mapping": {"start": 19509, "length": 317, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [474, 475, 476, 477, 478, 479, 480, 481, 482, 483], "starting_column": 13, "ending_column": 14}, "type_specific_fields": {"parent": {"type": "function", "name": "_deployL2Factory", "source_mapping": {"start": 18302, "length": 1541, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1AtomicTokenBridgeCreator", "source_mapping": {"start": 2114, "length": 23278, "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", "is_dependency": false, "lines": [52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619], "starting_column": 1, "ending_column": 2}}, "signature": "_deployL2Factory(address,uint256,address)"}}}}], "description": "L1AtomicTokenBridgeCreator._deployL2Factory(address,uint256,address) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#447-485) ignores return value by IInbox(inbox).createRetryableTicket{value: retryableFee_scope_0}(address(0),0,maxSubmissionCost,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,deploymentData) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#474-483)\n", "markdown": "[L1AtomicTokenBridgeCreator._deployL2Factory(address,uint256,address)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L447-L485) ignores return value by [IInbox(inbox).createRetryableTicket{value: retryableFee_scope_0}(address(0),0,maxSubmissionCost,msg.sender,msg.sender,gasLimitForL2FactoryDeployment,gasPriceBid,deploymentData)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L474-L483)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L447-L485", "id": "e020b241fb03d0676863525627c28d172830b0205edf229997b005753861a0e9", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_createRetryableUsingEth", "source_mapping": {"start": 6082, "length": 557, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_createRetryableUsingEth(RetryableParams,uint256,uint256,bytes)"}}, {"type": "node", "name": "IInbox(retryableParams.inbox).createRetryableTicket{value: value}(retryableParams.target,0,maxSubmissionCost,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,data)", "source_mapping": {"start": 6276, "length": 356, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [162, 163, 164, 165, 166, 167, 168, 169, 170, 171], "starting_column": 9, "ending_column": 10}, "type_specific_fields": {"parent": {"type": "function", "name": "_createRetryableUsingEth", "source_mapping": {"start": 6082, "length": 557, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_createRetryableUsingEth(RetryableParams,uint256,uint256,bytes)"}}}}], "description": "L1TokenBridgeRetryableSender._createRetryableUsingEth(RetryableParams,uint256,uint256,bytes) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#156-172) ignores return value by IInbox(retryableParams.inbox).createRetryableTicket{value: value}(retryableParams.target,0,maxSubmissionCost,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,data) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#162-171)\n", "markdown": "[L1TokenBridgeRetryableSender._createRetryableUsingEth(RetryableParams,uint256,uint256,bytes)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L156-L172) ignores return value by [IInbox(retryableParams.inbox).createRetryableTicket{value: value}(retryableParams.target,0,maxSubmissionCost,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,data)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L162-L171)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L156-L172", "id": "f3fce683bbb88d3bc3deac571c8226af666c3cd0ba19d493a68e53fcf76039c3", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_createRetryableUsingFeeToken", "source_mapping": {"start": 6645, "length": 531, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_createRetryableUsingFeeToken(RetryableParams,bytes)"}}, {"type": "node", "name": "IERC20Inbox(retryableParams.inbox).createRetryableTicket(retryableParams.target,0,0,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,retryableParams.feeTokenTotalFeeAmount,data)", "source_mapping": {"start": 6786, "length": 383, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188], "starting_column": 9, "ending_column": 10}, "type_specific_fields": {"parent": {"type": "function", "name": "_createRetryableUsingFeeToken", "source_mapping": {"start": 6645, "length": 531, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1TokenBridgeRetryableSender", "source_mapping": {"start": 1397, "length": 5781, "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190], "starting_column": 1, "ending_column": 2}}, "signature": "_createRetryableUsingFeeToken(RetryableParams,bytes)"}}}}], "description": "L1TokenBridgeRetryableSender._createRetryableUsingFeeToken(RetryableParams,bytes) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#174-189) ignores return value by IERC20Inbox(retryableParams.inbox).createRetryableTicket(retryableParams.target,0,0,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,retryableParams.feeTokenTotalFeeAmount,data) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#178-188)\n", "markdown": "[L1TokenBridgeRetryableSender._createRetryableUsingFeeToken(RetryableParams,bytes)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L174-L189) ignores return value by [IERC20Inbox(retryableParams.inbox).createRetryableTicket(retryableParams.target,0,0,retryableParams.excessFeeRefundAddress,retryableParams.callValueRefundAddress,retryableParams.maxGas,retryableParams.gasPriceBid,retryableParams.feeTokenTotalFeeAmount,data)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L178-L188)\n", "first_markdown_element": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L174-L189", "id": "b1f97e28632bc95bd065ae9a26c8acbdfd7cdd6155fe5910bf1567df8d76fe31", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}] \ No newline at end of file diff --git a/test-e2e/orbitTokenBridge.ts b/test-e2e/orbitTokenBridge.ts index 487eca46bc..7fc105f24e 100644 --- a/test-e2e/orbitTokenBridge.ts +++ b/test-e2e/orbitTokenBridge.ts @@ -17,24 +17,51 @@ import { ERC20, ERC20__factory, IERC20Bridge__factory, + IERC20__factory, IInbox__factory, + IOwnable__factory, + L1OrbitUSDCGateway__factory, + L1GatewayRouter__factory, + L1OrbitERC20Gateway__factory, L1OrbitGatewayRouter__factory, + L1USDCGateway__factory, L2CustomGateway__factory, L2GatewayRouter__factory, + L2USDCGateway__factory, + ProxyAdmin__factory, TestArbCustomToken__factory, + TestCustomTokenL1__factory, TestERC20, TestERC20__factory, TestOrbitCustomTokenL1__factory, + TransparentUpgradeableProxy__factory, + UpgradeExecutor__factory, + IFiatToken__factory, + IFiatTokenProxy__factory, } from '../build/types' import { defaultAbiCoder } from 'ethers/lib/utils' import { BigNumber, Wallet, ethers } from 'ethers' import { exit } from 'process' - +import { + abi as SigCheckerAbi, + bytecode as SigCheckerBytecode, +} from '@offchainlabs/stablecoin-evm/artifacts/hardhat/contracts/util/SignatureChecker.sol/SignatureChecker.json' +import { + abi as UsdcAbi, + bytecode as UsdcBytecode, +} from '@offchainlabs/stablecoin-evm/artifacts/hardhat/contracts/v2/FiatTokenV2_2.sol/FiatTokenV2_2.json' +import { + abi as UsdcProxyAbi, + bytecode as UsdcProxyBytecode, +} from '@offchainlabs/stablecoin-evm/artifacts/hardhat/contracts/v1/FiatTokenProxy.sol/FiatTokenProxy.json' const config = { parentUrl: 'http://127.0.0.1:8547', childUrl: 'http://127.0.0.1:3347', } +const LOCALHOST_L3_OWNER_KEY = + '0xecdf21cb41c65afb51f91df408b7656e2c8739a5877f2814add0afd780cc210e' + let parentProvider: JsonRpcProvider let childProvider: JsonRpcProvider @@ -49,7 +76,7 @@ let _l2Network: L2Network let token: TestERC20 let l2Token: ERC20 -let nativeToken: ERC20 +let nativeToken: ERC20 | undefined describe('orbitTokenBridge', () => { // configure orbit token bridge @@ -57,11 +84,30 @@ describe('orbitTokenBridge', () => { parentProvider = new ethers.providers.JsonRpcProvider(config.parentUrl) childProvider = new ethers.providers.JsonRpcProvider(config.childUrl) + TransparentUpgradeableProxy__factory + + const testDevKey = + '0xb6b15c8cb491557369f3c7d2c287b053eb229daa9c22138887752191c9520659' + const testDevL1Wallet = new ethers.Wallet(testDevKey, parentProvider) + const testDevL2Wallet = new ethers.Wallet(testDevKey, childProvider) + const deployerKey = ethers.utils.sha256( ethers.utils.toUtf8Bytes('user_token_bridge_deployer') ) deployerL1Wallet = new ethers.Wallet(deployerKey, parentProvider) deployerL2Wallet = new ethers.Wallet(deployerKey, childProvider) + await ( + await testDevL1Wallet.sendTransaction({ + to: deployerL1Wallet.address, + value: ethers.utils.parseEther('20.0'), + }) + ).wait() + await ( + await testDevL2Wallet.sendTransaction({ + to: deployerL2Wallet.address, + value: ethers.utils.parseEther('20.0'), + }) + ).wait() const { l1Network, l2Network } = await setupTokenBridgeInLocalEnv() @@ -78,6 +124,30 @@ describe('orbitTokenBridge', () => { value: ethers.utils.parseEther('10.0'), }) ).wait() + await ( + await deployerL2Wallet.sendTransaction({ + to: userL2Wallet.address, + value: ethers.utils.parseEther('10.0'), + }) + ).wait() + + const nativeTokenAddress = await getFeeToken( + l2Network.ethBridge.inbox, + parentProvider + ) + nativeToken = + nativeTokenAddress === ethers.constants.AddressZero + ? undefined + : ERC20__factory.connect(nativeTokenAddress, userL1Wallet) + + if (nativeToken) { + const supply = await nativeToken.balanceOf(deployerL1Wallet.address) + await ( + await nativeToken + .connect(deployerL1Wallet) + .transfer(userL1Wallet.address, supply.div(10)) + ).wait() + } }) it('should have deployed token bridge contracts', async function () { @@ -94,18 +164,17 @@ describe('orbitTokenBridge', () => { it('can deposit token via default gateway', async function () { // fund user to be able to pay retryable fees - nativeToken = ERC20__factory.connect( - await getFeeToken(_l2Network.ethBridge.inbox, userL1Wallet), - userL1Wallet - ) - await ( - await nativeToken - .connect(deployerL1Wallet) - .transfer( - userL1Wallet.address, - ethers.utils.parseUnits('100', await nativeToken.decimals()) - ) - ).wait() + if (nativeToken) { + await ( + await nativeToken + .connect(deployerL1Wallet) + .transfer( + userL1Wallet.address, + ethers.utils.parseUnits('100', await nativeToken.decimals()) + ) + ).wait() + nativeToken.connect(userL1Wallet) + } // create token to be bridged const tokenFactory = await new TestERC20__factory(userL1Wallet).deploy() @@ -114,15 +183,16 @@ describe('orbitTokenBridge', () => { // snapshot state before const userTokenBalanceBefore = await token.balanceOf(userL1Wallet.address) + const gatewayTokenBalanceBefore = await token.balanceOf( _l2Network.tokenBridge.l1ERC20Gateway ) - const userNativeTokenBalanceBefore = await nativeToken.balanceOf( - userL1Wallet.address - ) - const bridgeNativeTokenBalanceBefore = await nativeToken.balanceOf( - _l2Network.ethBridge.bridge - ) + const userNativeTokenBalanceBefore = nativeToken + ? await nativeToken.balanceOf(userL1Wallet.address) + : await parentProvider.getBalance(userL1Wallet.address) + const bridgeNativeTokenBalanceBefore = nativeToken + ? await nativeToken.balanceOf(_l2Network.ethBridge.bridge) + : await parentProvider.getBalance(_l2Network.ethBridge.bridge) // approve token const depositAmount = 120 @@ -130,34 +200,80 @@ describe('orbitTokenBridge', () => { await token.approve(_l2Network.tokenBridge.l1ERC20Gateway, depositAmount) ).wait() - // set retryable params - const maxSubmissionCost = 0 - const gasLimit = BigNumber.from(1000000) - const maxFeePerGas = BigNumber.from(300000000) - const tokenTotalFeeAmount = await _getScaledAmount( - nativeToken.address, - gasLimit.mul(maxFeePerGas), - nativeToken.provider! + // calculate retryable params + const maxSubmissionCost = nativeToken + ? BigNumber.from(0) + : BigNumber.from(584000000000) + const callhook = '0x' + + const gateway = L1OrbitERC20Gateway__factory.connect( + _l2Network.tokenBridge.l1ERC20Gateway, + userL1Wallet + ) + const outboundCalldata = await gateway.getOutboundCalldata( + token.address, + userL1Wallet.address, + userL2Wallet.address, + depositAmount, + callhook + ) + + const l1ToL2MessageGasEstimate = new L1ToL2MessageGasEstimator( + childProvider + ) + const retryableParams = await l1ToL2MessageGasEstimate.estimateAll( + { + from: userL1Wallet.address, + to: userL2Wallet.address, + l2CallValue: BigNumber.from(0), + excessFeeRefundAddress: userL1Wallet.address, + callValueRefundAddress: userL1Wallet.address, + data: outboundCalldata, + }, + await getBaseFee(parentProvider), + parentProvider ) + const gasLimit = retryableParams.gasLimit.mul(60) + const maxFeePerGas = retryableParams.maxFeePerGas + const tokenTotalFeeAmount = nativeToken + ? await _getScaledAmount( + nativeToken.address, + gasLimit.mul(maxFeePerGas).mul(2), + nativeToken.provider! + ) + : gasLimit.mul(maxFeePerGas).mul(2) + // approve fee amount - await ( - await nativeToken.approve( - _l2Network.tokenBridge.l1ERC20Gateway, - tokenTotalFeeAmount - ) - ).wait() + if (nativeToken) { + await ( + await nativeToken.approve( + _l2Network.tokenBridge.l1ERC20Gateway, + tokenTotalFeeAmount + ) + ).wait() + } // bridge it - const userEncodedData = defaultAbiCoder.encode( - ['uint256', 'bytes', 'uint256'], - [maxSubmissionCost, '0x', tokenTotalFeeAmount] - ) + const userEncodedData = nativeToken + ? defaultAbiCoder.encode( + ['uint256', 'bytes', 'uint256'], + [maxSubmissionCost, callhook, tokenTotalFeeAmount] + ) + : defaultAbiCoder.encode( + ['uint256', 'bytes'], + [maxSubmissionCost, callhook] + ) - const router = L1OrbitGatewayRouter__factory.connect( - _l2Network.tokenBridge.l1GatewayRouter, - userL1Wallet - ) + const router = nativeToken + ? L1OrbitGatewayRouter__factory.connect( + _l2Network.tokenBridge.l1GatewayRouter, + userL1Wallet + ) + : L1GatewayRouter__factory.connect( + _l2Network.tokenBridge.l1GatewayRouter, + userL1Wallet + ) const depositTx = await router.outboundTransferCustomRefund( token.address, @@ -166,7 +282,8 @@ describe('orbitTokenBridge', () => { depositAmount, gasLimit, maxFeePerGas, - userEncodedData + userEncodedData, + { value: nativeToken ? BigNumber.from(0) : tokenTotalFeeAmount } ) // wait for L2 msg to be executed @@ -192,16 +309,22 @@ describe('orbitTokenBridge', () => { depositAmount ) - const userNativeTokenBalanceAfter = await nativeToken.balanceOf( - userL1Wallet.address - ) - expect( - userNativeTokenBalanceBefore.sub(userNativeTokenBalanceAfter) - ).to.be.eq(tokenTotalFeeAmount) + const userNativeTokenBalanceAfter = nativeToken + ? await nativeToken.balanceOf(userL1Wallet.address) + : await parentProvider.getBalance(userL1Wallet.address) + if (nativeToken) { + expect( + userNativeTokenBalanceBefore.sub(userNativeTokenBalanceAfter) + ).to.be.eq(tokenTotalFeeAmount) + } else { + expect( + userNativeTokenBalanceBefore.sub(userNativeTokenBalanceAfter) + ).to.be.gte(tokenTotalFeeAmount.toNumber()) + } - const bridgeNativeTokenBalanceAfter = await nativeToken.balanceOf( - _l2Network.ethBridge.bridge - ) + const bridgeNativeTokenBalanceAfter = nativeToken + ? await nativeToken.balanceOf(_l2Network.ethBridge.bridge) + : await parentProvider.getBalance(_l2Network.ethBridge.bridge) expect( bridgeNativeTokenBalanceAfter.sub(bridgeNativeTokenBalanceBefore) ).to.be.eq(tokenTotalFeeAmount) @@ -272,41 +395,49 @@ describe('orbitTokenBridge', () => { it('can deposit token via custom gateway', async function () { // fund user to be able to pay retryable fees - nativeToken = ERC20__factory.connect( - await getFeeToken(_l2Network.ethBridge.inbox, userL1Wallet), - userL1Wallet - ) - await ( - await nativeToken - .connect(deployerL1Wallet) - .transfer( - userL1Wallet.address, - ethers.utils.parseUnits('100', await nativeToken.decimals()) - ) - ).wait() + if (nativeToken) { + await ( + await nativeToken + .connect(deployerL1Wallet) + .transfer( + userL1Wallet.address, + ethers.utils.parseUnits('100', await nativeToken.decimals()) + ) + ).wait() + } // create L1 custom token - const customL1TokenFactory = await new TestOrbitCustomTokenL1__factory( - userL1Wallet - ).deploy( - _l2Network.tokenBridge.l1CustomGateway, - _l2Network.tokenBridge.l1GatewayRouter - ) + const customL1TokenFactory = nativeToken + ? await new TestOrbitCustomTokenL1__factory(deployerL1Wallet).deploy( + _l2Network.tokenBridge.l1CustomGateway, + _l2Network.tokenBridge.l1GatewayRouter + ) + : await new TestCustomTokenL1__factory(deployerL1Wallet).deploy( + _l2Network.tokenBridge.l1CustomGateway, + _l2Network.tokenBridge.l1GatewayRouter + ) const customL1Token = await customL1TokenFactory.deployed() - await (await customL1Token.mint()).wait() + await (await customL1Token.connect(userL1Wallet).mint()).wait() // create L2 custom token - await depositNativeToL2() + if (nativeToken) { + await depositNativeToL2() + } const customL2TokenFactory = await new TestArbCustomToken__factory( - userL2Wallet + deployerL2Wallet ).deploy(_l2Network.tokenBridge.l2CustomGateway, customL1Token.address) const customL2Token = await customL2TokenFactory.deployed() // prepare custom gateway registration params - const router = L1OrbitGatewayRouter__factory.connect( - _l2Network.tokenBridge.l1GatewayRouter, - userL1Wallet - ) + const router = nativeToken + ? L1OrbitGatewayRouter__factory.connect( + _l2Network.tokenBridge.l1GatewayRouter, + userL1Wallet + ) + : L1GatewayRouter__factory.connect( + _l2Network.tokenBridge.l1GatewayRouter, + userL1Wallet + ) const l1ToL2MessageGasEstimate = new L1ToL2MessageGasEstimator( childProvider ) @@ -348,34 +479,47 @@ describe('orbitTokenBridge', () => { ) // approve fee amount - const gwFee = await _getScaledAmount( - nativeToken.address, - gwRetryableParams.deposit, - nativeToken.provider! - ) - const routerFee = await _getScaledAmount( - nativeToken.address, - routerRetryableParams.deposit, - nativeToken.provider! - ) - const registrationFee = gwFee.add(routerFee).mul(2) - await ( - await nativeToken.approve(customL1Token.address, registrationFee) - ).wait() + const valueForGateway = nativeToken + ? await _getScaledAmount( + nativeToken.address, + gwRetryableParams.deposit, + nativeToken.provider! + ) + : gwRetryableParams.deposit + const valueForRouter = nativeToken + ? await _getScaledAmount( + nativeToken.address, + routerRetryableParams.deposit, + nativeToken.provider! + ) + : routerRetryableParams.deposit + const registrationFee = valueForGateway.add(valueForRouter).mul(2) + if (nativeToken) { + await ( + await nativeToken.approve(customL1Token.address, registrationFee) + ).wait() + } // do the custom gateway registration const receipt = await ( - await customL1Token.registerTokenOnL2( - customL2Token.address, - gwRetryableParams.maxSubmissionCost, - routerRetryableParams.maxSubmissionCost, - gwRetryableParams.gasLimit, - routerRetryableParams.gasLimit, - BigNumber.from(100000000), - gwFee, - routerFee, - userL1Wallet.address - ) + await customL1Token + .connect(userL1Wallet) + .registerTokenOnL2( + customL2Token.address, + gwRetryableParams.maxSubmissionCost, + routerRetryableParams.maxSubmissionCost, + gwRetryableParams.gasLimit.mul(2), + routerRetryableParams.gasLimit.mul(2), + BigNumber.from(100000000), + valueForGateway, + valueForRouter, + userL1Wallet.address, + { + value: nativeToken + ? BigNumber.from(0) + : valueForGateway.add(valueForRouter), + } + ) ).wait() /// wait for execution of both tickets @@ -408,45 +552,58 @@ describe('orbitTokenBridge', () => { const gatewayTokenBalanceBefore = await customL1Token.balanceOf( _l2Network.tokenBridge.l1CustomGateway ) - const userNativeTokenBalanceBefore = await nativeToken.balanceOf( - userL1Wallet.address - ) - const bridgeNativeTokenBalanceBefore = await nativeToken.balanceOf( - _l2Network.ethBridge.bridge - ) + const userNativeTokenBalanceBefore = nativeToken + ? await nativeToken.balanceOf(userL1Wallet.address) + : await parentProvider.getBalance(userL1Wallet.address) + const bridgeNativeTokenBalanceBefore = nativeToken + ? await nativeToken.balanceOf(_l2Network.ethBridge.bridge) + : await parentProvider.getBalance(_l2Network.ethBridge.bridge) // approve token const depositAmount = 110 await ( - await customL1Token.approve( - _l2Network.tokenBridge.l1CustomGateway, - depositAmount - ) + await customL1Token + .connect(userL1Wallet) + .approve(_l2Network.tokenBridge.l1CustomGateway, depositAmount) ).wait() // calculate retryable params - const maxSubmissionCost = 0 + const maxSubmissionCost = nativeToken + ? BigNumber.from(0) + : BigNumber.from(584000000000) + const callhook = '0x' + const gasLimit = BigNumber.from(1000000) const maxFeePerGas = BigNumber.from(300000000) - const tokenTotalFeeAmount = await _getScaledAmount( - nativeToken.address, - gasLimit.mul(maxFeePerGas), - nativeToken.provider! - ) + const tokenTotalFeeAmount = nativeToken + ? await _getScaledAmount( + nativeToken.address, + gasLimit.mul(maxFeePerGas).mul(2), + nativeToken.provider! + ) + : gasLimit.mul(maxFeePerGas).mul(2) // approve fee amount - await ( - await nativeToken.approve( - _l2Network.tokenBridge.l1CustomGateway, - tokenTotalFeeAmount - ) - ).wait() + if (nativeToken) { + await ( + await nativeToken.approve( + _l2Network.tokenBridge.l1CustomGateway, + tokenTotalFeeAmount + ) + ).wait() + } // bridge it - const userEncodedData = defaultAbiCoder.encode( - ['uint256', 'bytes', 'uint256'], - [maxSubmissionCost, '0x', tokenTotalFeeAmount] - ) + const userEncodedData = nativeToken + ? defaultAbiCoder.encode( + ['uint256', 'bytes', 'uint256'], + [maxSubmissionCost, callhook, tokenTotalFeeAmount] + ) + : defaultAbiCoder.encode( + ['uint256', 'bytes'], + [BigNumber.from(334400000000), callhook] + ) + const depositTx = await router.outboundTransferCustomRefund( customL1Token.address, userL1Wallet.address, @@ -454,7 +611,8 @@ describe('orbitTokenBridge', () => { depositAmount, gasLimit, maxFeePerGas, - userEncodedData + userEncodedData, + { value: nativeToken ? BigNumber.from(0) : tokenTotalFeeAmount } ) // wait for L2 msg to be executed @@ -488,19 +646,749 @@ describe('orbitTokenBridge', () => { depositAmount ) - const userNativeTokenBalanceAfter = await nativeToken.balanceOf( - userL1Wallet.address - ) + const userNativeTokenBalanceAfter = nativeToken + ? await nativeToken.balanceOf(userL1Wallet.address) + : await parentProvider.getBalance(userL1Wallet.address) + if (nativeToken) { + expect( + userNativeTokenBalanceBefore.sub(userNativeTokenBalanceAfter) + ).to.be.eq(tokenTotalFeeAmount) + } else { + expect( + userNativeTokenBalanceBefore.sub(userNativeTokenBalanceAfter) + ).to.be.gte(tokenTotalFeeAmount.toNumber()) + } + const bridgeNativeTokenBalanceAfter = nativeToken + ? await nativeToken.balanceOf(_l2Network.ethBridge.bridge) + : await parentProvider.getBalance(_l2Network.ethBridge.bridge) expect( - userNativeTokenBalanceBefore.sub(userNativeTokenBalanceAfter) + bridgeNativeTokenBalanceAfter.sub(bridgeNativeTokenBalanceBefore) ).to.be.eq(tokenTotalFeeAmount) + }) + + it('can upgrade from bridged USDC to native USDC when eth is native token', async function () { + /// test applicable only for eth based chains + if (nativeToken) { + return + } + + /// create new L1 usdc gateway behind proxy + const proxyAdminFac = await new ProxyAdmin__factory( + deployerL1Wallet + ).deploy() + const proxyAdmin = await proxyAdminFac.deployed() + const l1USDCCustomGatewayFactory = await new L1USDCGateway__factory( + deployerL1Wallet + ).deploy() + const l1USDCCustomGatewayLogic = await l1USDCCustomGatewayFactory.deployed() + const tupFactory = await new TransparentUpgradeableProxy__factory( + deployerL1Wallet + ).deploy(l1USDCCustomGatewayLogic.address, proxyAdmin.address, '0x') + const tup = await tupFactory.deployed() + const l1USDCCustomGateway = L1USDCGateway__factory.connect( + tup.address, + deployerL1Wallet + ) + console.log('L1USDCGateway address: ', l1USDCCustomGateway.address) + + /// create new L2 usdc gateway behind proxy + const proxyAdminL2Fac = await new ProxyAdmin__factory( + deployerL2Wallet + ).deploy() + const proxyAdminL2 = await proxyAdminL2Fac.deployed() + const l2USDCCustomGatewayFactory = await new L2USDCGateway__factory( + deployerL2Wallet + ).deploy() + const l2USDCCustomGatewayLogic = await l2USDCCustomGatewayFactory.deployed() + const tupL2Factory = await new TransparentUpgradeableProxy__factory( + deployerL2Wallet + ).deploy(l2USDCCustomGatewayLogic.address, proxyAdminL2.address, '0x') + const tupL2 = await tupL2Factory.deployed() + const l2USDCCustomGateway = L2USDCGateway__factory.connect( + tupL2.address, + deployerL2Wallet + ) + console.log('L2USDCGateway address: ', l2USDCCustomGateway.address) + + /// create l1 usdc behind proxy + const l1UsdcLogic = await _deployUsdcToken(deployerL1Wallet) + const tupL1UsdcFactory = await new TransparentUpgradeableProxy__factory( + deployerL1Wallet + ).deploy(l1UsdcLogic.address, proxyAdmin.address, '0x') + const tupL1Usdc = await tupL1UsdcFactory.deployed() + const l1UsdcInit = IFiatToken__factory.connect( + tupL1Usdc.address, + deployerL1Wallet + ) + const masterMinterL1 = deployerL1Wallet + await ( + await l1UsdcInit.initialize( + 'USDC token', + 'USDC.e', + 'USD', + 6, + masterMinterL1.address, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, + deployerL2Wallet.address + ) + ).wait() + await (await l1UsdcInit.initializeV2('USDC')).wait() + await ( + await l1UsdcInit.initializeV2_1(ethers.Wallet.createRandom().address) + ).wait() + await (await l1UsdcInit.initializeV2_2([], 'USDC')).wait() + const l1Usdc = IERC20__factory.connect(l1UsdcInit.address, deployerL1Wallet) + console.log('L1 USDC address: ', l1Usdc.address) + + /// create l2 usdc behind proxy + const l2UsdcLogic = await _deployUsdcToken(deployerL2Wallet) + const l2UsdcProxyAddress = await _deployUsdcProxy( + deployerL2Wallet, + l2UsdcLogic.address, + proxyAdminL2.address + ) - const bridgeNativeTokenBalanceAfter = await nativeToken.balanceOf( - _l2Network.ethBridge.bridge + const l2UsdcFiatToken = IFiatToken__factory.connect( + l2UsdcProxyAddress, + deployerL2Wallet ) + const masterMinterL2 = deployerL2Wallet + await ( + await l2UsdcFiatToken.initialize( + 'USDC token', + 'USDC.e', + 'USD', + 6, + masterMinterL2.address, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, + deployerL2Wallet.address + ) + ).wait() + await (await l2UsdcFiatToken.initializeV2('USDC')).wait() + await ( + await l2UsdcFiatToken.initializeV2_1(ethers.Wallet.createRandom().address) + ).wait() + await (await l2UsdcFiatToken.initializeV2_2([], 'USDC.e')).wait() + const l2Usdc = IERC20__factory.connect( + l2UsdcFiatToken.address, + deployerL2Wallet + ) + console.log('L2 USDC address: ', l2Usdc.address) + + /// initialize gateways + await ( + await l1USDCCustomGateway.initialize( + l2USDCCustomGateway.address, + _l2Network.tokenBridge.l1GatewayRouter, + _l2Network.ethBridge.inbox, + l1Usdc.address, + l2Usdc.address, + deployerL1Wallet.address + ) + ).wait() + console.log('L1 USDC custom gateway initialized') + + await ( + await l2USDCCustomGateway.initialize( + l1USDCCustomGateway.address, + _l2Network.tokenBridge.l2GatewayRouter, + l1Usdc.address, + l2Usdc.address, + deployerL2Wallet.address + ) + ).wait() + console.log('L2 USDC custom gateway initialized') + + /// register USDC custom gateway + const router = L1GatewayRouter__factory.connect( + _l2Network.tokenBridge.l1GatewayRouter, + deployerL1Wallet + ) + const l2Router = L2GatewayRouter__factory.connect( + _l2Network.tokenBridge.l2GatewayRouter, + deployerL2Wallet + ) + const maxGas = BigNumber.from(500000) + const gasPriceBid = BigNumber.from(200000000) + let maxSubmissionCost = BigNumber.from(257600000000) + const registrationCalldata = router.interface.encodeFunctionData( + 'setGateways', + [ + [l1Usdc.address], + [l1USDCCustomGateway.address], + maxGas, + gasPriceBid, + maxSubmissionCost, + ] + ) + const rollupOwner = new Wallet(LOCALHOST_L3_OWNER_KEY, parentProvider) + const upExec = UpgradeExecutor__factory.connect( + await IOwnable__factory.connect( + _l2Network.ethBridge.rollup, + deployerL1Wallet + ).owner(), + rollupOwner + ) + const gwRegistrationTx = await upExec.executeCall( + router.address, + registrationCalldata, + { + value: maxGas.mul(gasPriceBid).add(maxSubmissionCost), + } + ) + await waitOnL2Msg(gwRegistrationTx) + console.log('USDC custom gateway registered') + + /// check gateway registration + expect(await router.getGateway(l1Usdc.address)).to.be.eq( + l1USDCCustomGateway.address + ) + expect(await l1USDCCustomGateway.depositsPaused()).to.be.eq(false) + expect(await l2Router.getGateway(l1Usdc.address)).to.be.eq( + l2USDCCustomGateway.address + ) + expect(await l2USDCCustomGateway.withdrawalsPaused()).to.be.eq(false) + + /// add minter role with max allowance to L2 gateway + await ( + await l2UsdcFiatToken + .connect(masterMinterL2) + .configureMinter( + l2USDCCustomGateway.address, + ethers.constants.MaxUint256 + ) + ).wait() expect( - bridgeNativeTokenBalanceAfter.sub(bridgeNativeTokenBalanceBefore) - ).to.be.eq(tokenTotalFeeAmount) + await l2UsdcFiatToken.isMinter(l2USDCCustomGateway.address) + ).to.be.eq(true) + console.log('Minter role with max allowance granted to L2 USDC gateway') + + /// mint some USDC to user + await ( + await l1UsdcInit + .connect(masterMinterL1) + .configureMinter( + masterMinterL1.address, + ethers.utils.parseEther('1000') + ) + ).wait() + await ( + await l1UsdcInit + .connect(masterMinterL1) + .mint(userL1Wallet.address, ethers.utils.parseEther('10')) + ).wait() + console.log('Minted USDC to user') + + /// do a deposit + const depositAmount = ethers.utils.parseEther('2') + await ( + await l1Usdc + .connect(userL1Wallet) + .approve(l1USDCCustomGateway.address, depositAmount) + ).wait() + maxSubmissionCost = BigNumber.from(334400000000) + const depositTx = await router + .connect(userL1Wallet) + .outboundTransferCustomRefund( + l1Usdc.address, + userL2Wallet.address, + userL2Wallet.address, + depositAmount, + maxGas, + gasPriceBid, + defaultAbiCoder.encode(['uint256', 'bytes'], [maxSubmissionCost, '0x']), + { value: maxGas.mul(gasPriceBid).add(maxSubmissionCost) } + ) + await waitOnL2Msg(depositTx) + expect(await l2Usdc.balanceOf(userL2Wallet.address)).to.be.eq(depositAmount) + expect(await l1Usdc.balanceOf(l1USDCCustomGateway.address)).to.be.eq( + depositAmount + ) + expect(await l2Usdc.totalSupply()).to.be.eq(depositAmount) + console.log('Deposited USDC') + + /// pause deposits + await (await l1USDCCustomGateway.pauseDeposits()).wait() + expect(await l1USDCCustomGateway.depositsPaused()).to.be.eq(true) + console.log('Deposits paused') + + /// pause withdrawals + await (await l2USDCCustomGateway.pauseWithdrawals()).wait() + expect(await l2USDCCustomGateway.withdrawalsPaused()).to.be.eq(true) + console.log('Withdrawals paused') + + /// chain owner/circle checks that all pending deposits (all retryables depositing usdc) are executed + + // set burn amount + const burnAmount = await l2Usdc.totalSupply() + await (await l1USDCCustomGateway.setBurnAmount(burnAmount)).wait() + expect(await l1USDCCustomGateway.burnAmount()).to.be.eq(burnAmount) + console.log('Burn amount set') + + /// make circle the burner + const circleWalletL1 = ethers.Wallet.createRandom().connect(parentProvider) + await ( + await deployerL1Wallet.sendTransaction({ + to: circleWalletL1.address, + value: ethers.utils.parseEther('1'), + }) + ).wait() + await (await l1USDCCustomGateway.setBurner(circleWalletL1.address)).wait() + expect(await l1USDCCustomGateway.burner()).to.be.eq(circleWalletL1.address) + + /// add minter rights to usdc gateway so it can burn USDC + await ( + await l1UsdcInit.configureMinter(l1USDCCustomGateway.address, 0) + ).wait() + console.log('Minter role with 0 allowance added to L1 USDC gateway') + + /// remove minter role from the L2 gateway + await ( + await l2UsdcFiatToken + .connect(masterMinterL2) + .removeMinter(l2USDCCustomGateway.address) + ).wait() + expect( + await l2UsdcFiatToken.isMinter(l2USDCCustomGateway.address) + ).to.be.eq(false) + console.log('Minter role removed from L2 USDC gateway') + + /// set USDC role transferrer + const circleWalletL2 = ethers.Wallet.createRandom().connect(childProvider) + await ( + await deployerL2Wallet.sendTransaction({ + to: circleWalletL2.address, + value: ethers.utils.parseEther('1'), + }) + ).wait() + await ( + await l2USDCCustomGateway.setUsdcOwnershipTransferrer( + circleWalletL2.address + ) + ).wait() + expect(await l2USDCCustomGateway.usdcOwnershipTransferrer()).to.be.eq( + circleWalletL2.address + ) + console.log('USDC ownership transferrer set to', circleWalletL2.address) + + /// transfer child chain USDC ownership to gateway + await ( + await l2UsdcFiatToken.transferOwnership(l2USDCCustomGateway.address) + ).wait() + expect(await l2UsdcFiatToken.owner()).to.be.eq(l2USDCCustomGateway.address) + console.log('USDC ownership transferred to gateway') + + /// transfer proxyAdmin to gateway + const fiatTokenProxy = IFiatTokenProxy__factory.connect( + l2UsdcFiatToken.address, + deployerL2Wallet + ) + await ( + await proxyAdminL2.changeProxyAdmin( + fiatTokenProxy.address, + l2USDCCustomGateway.address + ) + ).wait() + expect(await fiatTokenProxy.admin()).to.be.eq(l2USDCCustomGateway.address) + console.log('Proxy admin transferred to gateway') + + /// transfer child chain USDC ownership to circle + await ( + await l2USDCCustomGateway + .connect(circleWalletL2) + .transferUSDCRoles(circleWalletL2.address) + ).wait() + + expect(await l2UsdcFiatToken.owner()).to.be.eq(circleWalletL2.address) + expect(await fiatTokenProxy.admin()).to.be.eq(circleWalletL2.address) + console.log('USDC ownership transferred to circle') + + /// circle burns USDC on L1 + await ( + await l1USDCCustomGateway.connect(circleWalletL1).burnLockedUSDC() + ).wait() + expect(await l1Usdc.balanceOf(l1USDCCustomGateway.address)).to.be.eq(0) + expect(await l2Usdc.balanceOf(userL2Wallet.address)).to.be.eq(depositAmount) + console.log('USDC burned') + }) + + it('can upgrade from bridged USDC to native USDC when fee token is used', async function () { + /// test applicable only for fee token based chains + if (!nativeToken) { + return + } + + /// create new L1 usdc gateway behind proxy + const proxyAdminFac = await new ProxyAdmin__factory( + deployerL1Wallet + ).deploy() + const proxyAdmin = await proxyAdminFac.deployed() + const l1USDCCustomGatewayFactory = await new L1OrbitUSDCGateway__factory( + deployerL1Wallet + ).deploy() + const l1USDCCustomGatewayLogic = await l1USDCCustomGatewayFactory.deployed() + const tupFactory = await new TransparentUpgradeableProxy__factory( + deployerL1Wallet + ).deploy(l1USDCCustomGatewayLogic.address, proxyAdmin.address, '0x') + const tup = await tupFactory.deployed() + const l1USDCCustomGateway = L1USDCGateway__factory.connect( + tup.address, + deployerL1Wallet + ) + console.log('L1USDCGateway address: ', l1USDCCustomGateway.address) + + /// create new L2 usdc gateway behind proxy + const proxyAdminL2Fac = await new ProxyAdmin__factory( + deployerL2Wallet + ).deploy() + const proxyAdminL2 = await proxyAdminL2Fac.deployed() + const l2USDCCustomGatewayFactory = await new L2USDCGateway__factory( + deployerL2Wallet + ).deploy() + const l2USDCCustomGatewayLogic = await l2USDCCustomGatewayFactory.deployed() + const tupL2Factory = await new TransparentUpgradeableProxy__factory( + deployerL2Wallet + ).deploy(l2USDCCustomGatewayLogic.address, proxyAdminL2.address, '0x') + const tupL2 = await tupL2Factory.deployed() + const l2USDCCustomGateway = L2USDCGateway__factory.connect( + tupL2.address, + deployerL2Wallet + ) + console.log('L2USDCGateway address: ', l2USDCCustomGateway.address) + + /// create l1 usdc behind proxy + const l1UsdcLogic = await _deployUsdcToken(deployerL1Wallet) + const tupL1UsdcFactory = await new TransparentUpgradeableProxy__factory( + deployerL1Wallet + ).deploy(l1UsdcLogic.address, proxyAdmin.address, '0x') + const tupL1Usdc = await tupL1UsdcFactory.deployed() + const l1UsdcInit = IFiatToken__factory.connect( + tupL1Usdc.address, + deployerL1Wallet + ) + const masterMinterL1 = deployerL1Wallet + await ( + await l1UsdcInit.initialize( + 'USDC token', + 'USDC.e', + 'USD', + 6, + masterMinterL1.address, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, + deployerL2Wallet.address + ) + ).wait() + await (await l1UsdcInit.initializeV2('USDC')).wait() + await ( + await l1UsdcInit.initializeV2_1(ethers.Wallet.createRandom().address) + ).wait() + await (await l1UsdcInit.initializeV2_2([], 'USDC')).wait() + const l1Usdc = IERC20__factory.connect(l1UsdcInit.address, deployerL1Wallet) + console.log('L1 USDC address: ', l1Usdc.address) + + /// create l2 usdc behind proxy + const l2UsdcLogic = await _deployUsdcToken(deployerL2Wallet) + const l2UsdcProxyAddress = await _deployUsdcProxy( + deployerL2Wallet, + l2UsdcLogic.address, + proxyAdminL2.address + ) + + const l2UsdcFiatToken = IFiatToken__factory.connect( + l2UsdcProxyAddress, + deployerL2Wallet + ) + const masterMinterL2 = deployerL2Wallet + await ( + await l2UsdcFiatToken.initialize( + 'USDC token', + 'USDC.e', + 'USD', + 6, + masterMinterL2.address, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, + deployerL2Wallet.address + ) + ).wait() + await (await l2UsdcFiatToken.initializeV2('USDC')).wait() + await ( + await l2UsdcFiatToken.initializeV2_1(ethers.Wallet.createRandom().address) + ).wait() + await (await l2UsdcFiatToken.initializeV2_2([], 'USDC.e')).wait() + const l2Usdc = IERC20__factory.connect( + l2UsdcFiatToken.address, + deployerL2Wallet + ) + console.log('L2 USDC address: ', l2Usdc.address) + + /// initialize gateways + await ( + await l1USDCCustomGateway.initialize( + l2USDCCustomGateway.address, + _l2Network.tokenBridge.l1GatewayRouter, + _l2Network.ethBridge.inbox, + l1Usdc.address, + l2Usdc.address, + deployerL1Wallet.address + ) + ).wait() + console.log('L1 USDC custom gateway initialized') + + await ( + await l2USDCCustomGateway.initialize( + l1USDCCustomGateway.address, + _l2Network.tokenBridge.l2GatewayRouter, + l1Usdc.address, + l2Usdc.address, + deployerL2Wallet.address + ) + ).wait() + console.log('L2 USDC custom gateway initialized') + + /// register USDC custom gateway + const router = L1OrbitGatewayRouter__factory.connect( + _l2Network.tokenBridge.l1GatewayRouter, + deployerL1Wallet + ) + const l2Router = L2GatewayRouter__factory.connect( + _l2Network.tokenBridge.l2GatewayRouter, + deployerL2Wallet + ) + const maxGas = BigNumber.from(500000) + const gasPriceBid = BigNumber.from(200000000) + const totalFeeTokenAmount = await _getScaledAmount( + nativeToken!.address, + maxGas.mul(gasPriceBid), + nativeToken!.provider + ) + const maxSubmissionCost = BigNumber.from(0) + + // prefund inbox to pay for registration + await ( + await nativeToken + .connect(deployerL1Wallet) + .transfer(_l2Network.ethBridge.inbox, totalFeeTokenAmount) + ).wait() + + const registrationCalldata = (router.interface as any).encodeFunctionData( + 'setGateways(address[],address[],uint256,uint256,uint256,uint256)', + [ + [l1Usdc.address], + [l1USDCCustomGateway.address], + maxGas, + gasPriceBid, + maxSubmissionCost, + totalFeeTokenAmount, + ] + ) + const rollupOwner = new Wallet(LOCALHOST_L3_OWNER_KEY, parentProvider) + // approve fee amount + console.log('Approving fee amount') + await ( + await nativeToken + .connect(rollupOwner) + .approve(l1USDCCustomGateway.address, totalFeeTokenAmount) + ).wait() + + const upExec = UpgradeExecutor__factory.connect( + await IOwnable__factory.connect( + _l2Network.ethBridge.rollup, + deployerL1Wallet + ).owner(), + rollupOwner + ) + const gwRegistrationTx = await upExec.executeCall( + router.address, + registrationCalldata + ) + await waitOnL2Msg(gwRegistrationTx) + console.log('USDC custom gateway registered') + + /// check gateway registration + expect(await router.getGateway(l1Usdc.address)).to.be.eq( + l1USDCCustomGateway.address + ) + expect(await l1USDCCustomGateway.depositsPaused()).to.be.eq(false) + expect(await l2Router.getGateway(l1Usdc.address)).to.be.eq( + l2USDCCustomGateway.address + ) + expect(await l2USDCCustomGateway.withdrawalsPaused()).to.be.eq(false) + + /// add minter role with max allowance to L2 gateway + await ( + await l2UsdcFiatToken + .connect(masterMinterL2) + .configureMinter( + l2USDCCustomGateway.address, + ethers.constants.MaxUint256 + ) + ).wait() + expect( + await l2UsdcFiatToken.isMinter(l2USDCCustomGateway.address) + ).to.be.eq(true) + console.log('Minter role with max allowance granted to L2 USDC gateway') + + /// mint some USDC to user + await ( + await l1UsdcInit + .connect(masterMinterL1) + .configureMinter( + masterMinterL1.address, + ethers.utils.parseEther('1000') + ) + ).wait() + await ( + await l1UsdcInit + .connect(masterMinterL1) + .mint(userL1Wallet.address, ethers.utils.parseEther('10')) + ).wait() + console.log('Minted USDC to user') + + /// do a deposit + const depositAmount = ethers.utils.parseEther('2') + await ( + await l1Usdc + .connect(userL1Wallet) + .approve(l1USDCCustomGateway.address, depositAmount) + ).wait() + + // approve fee amount + await ( + await nativeToken + .connect(userL1Wallet) + .approve(l1USDCCustomGateway.address, totalFeeTokenAmount) + ).wait() + + const depositTx = await router + .connect(userL1Wallet) + .outboundTransferCustomRefund( + l1Usdc.address, + userL2Wallet.address, + userL2Wallet.address, + depositAmount, + maxGas, + gasPriceBid, + defaultAbiCoder.encode( + ['uint256', 'bytes', 'uint256'], + [maxSubmissionCost, '0x', totalFeeTokenAmount] + ) + ) + await waitOnL2Msg(depositTx) + expect(await l2Usdc.balanceOf(userL2Wallet.address)).to.be.eq(depositAmount) + expect(await l1Usdc.balanceOf(l1USDCCustomGateway.address)).to.be.eq( + depositAmount + ) + expect(await l2Usdc.totalSupply()).to.be.eq(depositAmount) + console.log('Deposited USDC') + + /// pause deposits + await (await l1USDCCustomGateway.pauseDeposits()).wait() + expect(await l1USDCCustomGateway.depositsPaused()).to.be.eq(true) + console.log('Deposits paused') + + /// pause withdrawals + await (await l2USDCCustomGateway.pauseWithdrawals()).wait() + expect(await l2USDCCustomGateway.withdrawalsPaused()).to.be.eq(true) + console.log('Withdrawals paused') + + /// chain owner/circle checks that all pending deposits (all retryables depositing usdc) are executed + + // set burn amount + const burnAmount = await l2Usdc.totalSupply() + await (await l1USDCCustomGateway.setBurnAmount(burnAmount)).wait() + expect(await l1USDCCustomGateway.burnAmount()).to.be.eq(burnAmount) + console.log('Burn amount set') + + /// make circle the burner + const circleWalletL1 = ethers.Wallet.createRandom().connect(parentProvider) + await ( + await deployerL1Wallet.sendTransaction({ + to: circleWalletL1.address, + value: ethers.utils.parseEther('1'), + }) + ).wait() + await (await l1USDCCustomGateway.setBurner(circleWalletL1.address)).wait() + expect(await l1USDCCustomGateway.burner()).to.be.eq(circleWalletL1.address) + console.log('Circle set as burner') + + /// add minter rights to usdc gateway so it can burn USDC + await ( + await l1UsdcInit.configureMinter(l1USDCCustomGateway.address, 0) + ).wait() + console.log('Minter role with 0 allowance added to L1 USDC gateway') + + /// remove minter role from the L2 gateway + await ( + await l2UsdcFiatToken + .connect(masterMinterL2) + .removeMinter(l2USDCCustomGateway.address) + ).wait() + expect( + await l2UsdcFiatToken.isMinter(l2USDCCustomGateway.address) + ).to.be.eq(false) + console.log('Minter role removed from L2 USDC gateway') + + /// set USDC role transferrer + const circleWalletL2 = ethers.Wallet.createRandom().connect(childProvider) + await ( + await deployerL2Wallet.sendTransaction({ + to: circleWalletL2.address, + value: ethers.utils.parseEther('1'), + }) + ).wait() + await ( + await l2USDCCustomGateway.setUsdcOwnershipTransferrer( + circleWalletL2.address + ) + ).wait() + expect(await l2USDCCustomGateway.usdcOwnershipTransferrer()).to.be.eq( + circleWalletL2.address + ) + console.log('USDC ownership transferrer set to', circleWalletL2.address) + + /// transfer child chain USDC ownership to gateway + await ( + await l2UsdcFiatToken.transferOwnership(l2USDCCustomGateway.address) + ).wait() + expect(await l2UsdcFiatToken.owner()).to.be.eq(l2USDCCustomGateway.address) + console.log('USDC ownership transferred to gateway') + + /// transfer proxyAdmin to gateway + const fiatTokenProxy = IFiatTokenProxy__factory.connect( + l2UsdcFiatToken.address, + deployerL2Wallet + ) + await ( + await proxyAdminL2.changeProxyAdmin( + fiatTokenProxy.address, + l2USDCCustomGateway.address + ) + ).wait() + expect(await fiatTokenProxy.admin()).to.be.eq(l2USDCCustomGateway.address) + console.log('Proxy admin transferred to gateway') + + /// transfer child chain USDC ownership to circle + await ( + await l2USDCCustomGateway + .connect(circleWalletL2) + .transferUSDCRoles(circleWalletL2.address) + ).wait() + + expect(await l2UsdcFiatToken.owner()).to.be.eq(circleWalletL2.address) + expect(await fiatTokenProxy.admin()).to.be.eq(circleWalletL2.address) + console.log('USDC ownership transferred to circle') + + /// circle burns USDC on L1 + await ( + await l1USDCCustomGateway.connect(circleWalletL1).burnLockedUSDC() + ).wait() + expect(await l1Usdc.balanceOf(l1USDCCustomGateway.address)).to.be.eq(0) + expect(await l2Usdc.balanceOf(userL2Wallet.address)).to.be.eq(depositAmount) + console.log('USDC burned') }) }) @@ -511,10 +1399,10 @@ async function depositNativeToL2() { /// deposit tokens const amountToDeposit = ethers.utils.parseUnits( '2.0', - await nativeToken.decimals() + await nativeToken!.decimals() ) await ( - await nativeToken + await nativeToken! .connect(userL1Wallet) .approve(_l2Network.ethBridge.inbox, amountToDeposit) ).wait() @@ -574,3 +1462,54 @@ const getFeeToken = async (inbox: string, parentProvider: any) => { function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)) } + +async function _deployUsdcToken(deployer: Wallet) { + /// deploy library + const sigCheckerFac = new ethers.ContractFactory( + SigCheckerAbi, + SigCheckerBytecode, + deployer + ) + const sigCheckerLib = await sigCheckerFac.deploy() + + // prepare bridged usdc bytecode + const bytecodeWithPlaceholder: string = UsdcBytecode + const placeholder = '__$715109b5d747ea58b675c6ea3f0dba8c60$__' + + const libAddressStripped = sigCheckerLib.address.replace(/^0x/, '') + const bridgedUsdcLogicBytecode = bytecodeWithPlaceholder + .split(placeholder) + .join(libAddressStripped) + + // deploy bridged usdc logic + const bridgedUsdcLogicFactory = new ethers.ContractFactory( + UsdcAbi, + bridgedUsdcLogicBytecode, + deployer + ) + const bridgedUsdcLogic = await bridgedUsdcLogicFactory.deploy() + + return bridgedUsdcLogic +} + +async function _deployUsdcProxy( + deployer: Wallet, + bridgedUsdcLogic: string, + proxyAdmin: string +) { + const usdcProxyFactory = new ethers.ContractFactory( + UsdcProxyAbi, + UsdcProxyBytecode, + deployer + ) + const usdcProxy = await usdcProxyFactory.deploy(bridgedUsdcLogic) + + await ( + await IFiatTokenProxy__factory.connect( + usdcProxy.address, + deployer + ).changeAdmin(proxyAdmin) + ).wait() + + return usdcProxy.address +} diff --git a/test-foundry/L1OrbitUSDCGateway.t.sol b/test-foundry/L1OrbitUSDCGateway.t.sol new file mode 100644 index 0000000000..bda25b5af7 --- /dev/null +++ b/test-foundry/L1OrbitUSDCGateway.t.sol @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import "./L1USDCGateway.t.sol"; +import {L1OrbitUSDCGateway} from "contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol"; +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {ERC20InboxMock} from "contracts/tokenbridge/test/InboxMock.sol"; +import {ERC20PresetMinterPauser} from + "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; + +contract L1OrbitUSDCGatewayTest is L1USDCGatewayTest { + ERC20 public nativeToken; + uint256 public nativeTokenTotalFee; + + function setUp() public virtual override { + inbox = address(new ERC20InboxMock()); + InboxMock(inbox).setL2ToL1Sender(l2Gateway); + + nativeToken = ERC20(address(new ERC20PresetMinterPauser("X", "Y"))); + ERC20PresetMinterPauser(address(nativeToken)).mint(user, 1_000_000 ether); + ERC20PresetMinterPauser(address(nativeToken)).mint(owner, 1_000_000 ether); + ERC20InboxMock(inbox).setMockNativeToken(address(nativeToken)); + + usdcGateway = new L1OrbitUSDCGateway(); + l1Gateway = IL1ArbitrumGateway(address(usdcGateway)); + + L1OrbitUSDCGateway(address(l1Gateway)).initialize( + l2Gateway, router, inbox, L1_USDC, L2_USDC, owner + ); + + maxSubmissionCost = 0; + nativeTokenTotalFee = maxGas * gasPriceBid; + + // fund user and router + vm.deal(router, 100 ether); + vm.deal(owner, 100 ether); + } + + function test_outboundTransfer() public override { + uint256 depositAmount = 300; + deal(L1_USDC, user, depositAmount); + bytes memory routerEncodedData = buildRouterEncodedData(""); + + // snapshot state before + uint256 userNativeTokenBalanceBefore = nativeToken.balanceOf(user); + uint256 userBalanceBefore = ERC20(L1_USDC).balanceOf(user); + uint256 l1GatewayBalanceBefore = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + + // approve token + vm.prank(user); + ERC20(L1_USDC).approve(address(l1Gateway), depositAmount); + + // approve fees + vm.prank(user); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + + // event checkers + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(user, user); + + vm.expectEmit(true, true, true, true); + emit ERC20InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + l1Gateway.getOutboundCalldata(L1_USDC, user, user, 300, "") + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(L1_USDC, user, user, 0, depositAmount); + + // trigger deposit + vm.prank(router); + + bytes memory seqNum = l1Gateway.outboundTransfer( + L1_USDC, user, depositAmount, maxGas, gasPriceBid, routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = ERC20(L1_USDC).balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + + uint256 userNativeTokenBalanceAfter = nativeToken.balanceOf(user); + assertEq( + userNativeTokenBalanceBefore - userNativeTokenBalanceAfter, + nativeTokenTotalFee, + "Wrong user native token balance" + ); + + assertEq(seqNum, abi.encode(0), "Invalid seqNum"); + } + + function test_outboundTransferCustomRefund() public override { + uint256 depositAmount = 100; + deal(L1_USDC, user, depositAmount); + bytes memory routerEncodedData = buildRouterEncodedData(""); + + // snapshot state before + uint256 userNativeTokenBalanceBefore = nativeToken.balanceOf(user); + uint256 userBalanceBefore = ERC20(L1_USDC).balanceOf(user); + uint256 l1GatewayBalanceBefore = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + + // approve token + vm.prank(user); + ERC20(L1_USDC).approve(address(l1Gateway), depositAmount); + + // approve fees + vm.prank(user); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + + // event checkers + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(creditBackAddress, user); + + vm.expectEmit(true, true, true, true); + emit ERC20InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + l1Gateway.getOutboundCalldata(L1_USDC, user, user, 100, "") + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(L1_USDC, user, user, 0, depositAmount); + + // trigger deposit + vm.prank(router); + + bytes memory seqNum = l1Gateway.outboundTransferCustomRefund( + L1_USDC, creditBackAddress, user, depositAmount, maxGas, gasPriceBid, routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = ERC20(L1_USDC).balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + + uint256 userNativeTokenBalanceAfter = nativeToken.balanceOf(user); + assertEq( + userNativeTokenBalanceBefore - userNativeTokenBalanceAfter, + nativeTokenTotalFee, + "Wrong user native token balance" + ); + + assertEq(seqNum, abi.encode(0), "Invalid seqNum"); + } + + function test_outboundTransferCustomRefund_InboxPrefunded() public { + uint256 depositAmount = 100; + deal(L1_USDC, user, depositAmount); + bytes memory routerEncodedData = buildRouterEncodedData(""); + + // pre-fund inbox + address inbox = address(l1Gateway.inbox()); + vm.prank(user); + nativeToken.transfer(inbox, nativeTokenTotalFee * 2); + + // snapshot state before + uint256 userNativeTokenBalanceBefore = nativeToken.balanceOf(user); + uint256 userBalanceBefore = ERC20(L1_USDC).balanceOf(user); + uint256 l1GatewayBalanceBefore = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + + // approve token + vm.prank(user); + ERC20(L1_USDC).approve(address(l1Gateway), depositAmount); + + // approve fees + vm.prank(user); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + + // event checkers + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(creditBackAddress, user); + + vm.expectEmit(true, true, true, true); + emit ERC20InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + l1Gateway.getOutboundCalldata(L1_USDC, user, user, 100, "") + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(L1_USDC, user, user, 0, depositAmount); + + // trigger deposit + vm.prank(router); + + bytes memory seqNum = l1Gateway.outboundTransferCustomRefund( + L1_USDC, creditBackAddress, user, depositAmount, maxGas, gasPriceBid, routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = ERC20(L1_USDC).balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + + uint256 userNativeTokenBalanceAfter = nativeToken.balanceOf(user); + assertEq( + userNativeTokenBalanceAfter, + userNativeTokenBalanceBefore, + "Wrong user native token balance" + ); + + assertEq(seqNum, abi.encode(0), "Invalid seqNum"); + } + + function test_outboundTransferCustomRefund_InboxPartiallyPrefunded() public { + uint256 depositAmount = 100; + deal(L1_USDC, user, depositAmount); + bytes memory routerEncodedData = buildRouterEncodedData(""); + + // pre-fund inbox + uint256 prefundAmount = nativeTokenTotalFee / 3; + address inbox = address(l1Gateway.inbox()); + vm.prank(user); + nativeToken.transfer(inbox, prefundAmount); + + // snapshot state before + uint256 userNativeTokenBalanceBefore = nativeToken.balanceOf(user); + uint256 userBalanceBefore = ERC20(L1_USDC).balanceOf(user); + uint256 l1GatewayBalanceBefore = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + + // approve token + vm.prank(user); + ERC20(L1_USDC).approve(address(l1Gateway), depositAmount); + + // approve fees + vm.prank(user); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee - prefundAmount); + + // event checkers + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(creditBackAddress, user); + + vm.expectEmit(true, true, true, true); + emit ERC20InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + l1Gateway.getOutboundCalldata(L1_USDC, user, user, 100, "") + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(L1_USDC, user, user, 0, depositAmount); + + // trigger deposit + vm.prank(router); + + bytes memory seqNum = l1Gateway.outboundTransferCustomRefund( + L1_USDC, creditBackAddress, user, depositAmount, maxGas, gasPriceBid, routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = ERC20(L1_USDC).balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + + uint256 userNativeTokenBalanceAfter = nativeToken.balanceOf(user); + assertEq( + userNativeTokenBalanceBefore - userNativeTokenBalanceAfter, + nativeTokenTotalFee - prefundAmount, + "Wrong user native token balance" + ); + + assertEq(seqNum, abi.encode(0), "Invalid seqNum"); + } + + /// + // Helper functions + /// + function buildRouterEncodedData(bytes memory callHookData) + internal + view + override + returns (bytes memory) + { + bytes memory userEncodedData = + abi.encode(maxSubmissionCost, callHookData, nativeTokenTotalFee); + bytes memory routerEncodedData = abi.encode(user, userEncodedData); + + return routerEncodedData; + } + + event ERC20InboxRetryableTicket( + address from, + address to, + uint256 l2CallValue, + uint256 maxGas, + uint256 gasPriceBid, + uint256 tokenTotalFeeAmount, + bytes data + ); +} diff --git a/test-foundry/L1USDCGateway.t.sol b/test-foundry/L1USDCGateway.t.sol new file mode 100644 index 0000000000..3b69be6566 --- /dev/null +++ b/test-foundry/L1USDCGateway.t.sol @@ -0,0 +1,467 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import "./L1ArbitrumExtendedGateway.t.sol"; +import {L1USDCGateway} from "contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol"; +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract L1USDCGatewayTest is L1ArbitrumExtendedGatewayTest { + L1USDCGateway usdcGateway; + address public owner = makeAddr("gw-owner"); + address public L1_USDC = address(new MockUsdc()); + address public L2_USDC = makeAddr("L2_USDC"); + + function setUp() public virtual { + inbox = address(new InboxMock()); + InboxMock(inbox).setL2ToL1Sender(l2Gateway); + + l1Gateway = new L1USDCGateway(); + usdcGateway = L1USDCGateway(payable(address(l1Gateway))); + usdcGateway.initialize(l2Gateway, router, inbox, L1_USDC, L2_USDC, owner); + + maxSubmissionCost = 4000; + retryableCost = maxSubmissionCost + gasPriceBid * maxGas; + + vm.deal(owner, 100 ether); + } + + /* solhint-disable func-name-mixedcase */ + function test_burnLockedUSDC() public { + /// add some USDC to the gateway + uint256 lockedAmount = 234 ether; + deal(L1_USDC, address(usdcGateway), lockedAmount); + assertEq( + ERC20(L1_USDC).balanceOf(address(usdcGateway)), lockedAmount, "Invalid USDC balance" + ); + + /// pause deposits + vm.prank(owner); + usdcGateway.pauseDeposits(); + + /// set burner + address burner = makeAddr("burner"); + vm.prank(owner); + usdcGateway.setBurner(burner); + + /// set burn amount + vm.prank(owner); + uint256 l2Supply = lockedAmount - 100; + usdcGateway.setBurnAmount(l2Supply); + + vm.expectEmit(true, true, true, true); + emit GatewayUsdcBurned(l2Supply); + + /// burn USDC + vm.prank(burner); + usdcGateway.burnLockedUSDC(); + + /// checks + assertEq( + ERC20(L1_USDC).balanceOf(address(usdcGateway)), + lockedAmount - l2Supply, + "Invalid USDC balance" + ); + } + + function test_burnLockedUSDC_revert_NotOwner() public { + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_NotBurner.selector)); + usdcGateway.burnLockedUSDC(); + } + + function test_burnLockedUSDC_revert_NotPaused() public { + /// set burner + address burner = makeAddr("burner"); + vm.prank(owner); + usdcGateway.setBurner(burner); + + vm.prank(burner); + vm.expectRevert( + abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_DepositsNotPaused.selector) + ); + usdcGateway.burnLockedUSDC(); + } + + function test_burnLockedUSDC_revert_BurnAmountNotSet() public { + /// add some USDC to the gateway + uint256 lockedAmount = 234 ether; + deal(L1_USDC, address(usdcGateway), lockedAmount); + + /// pause deposits + vm.prank(owner); + usdcGateway.pauseDeposits(); + + /// set burner + address burner = makeAddr("burner"); + vm.prank(owner); + usdcGateway.setBurner(burner); + + vm.expectRevert( + abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_BurnAmountNotSet.selector) + ); + vm.prank(burner); + usdcGateway.burnLockedUSDC(); + } + + function test_calculateL2TokenAddress() public { + assertEq(l1Gateway.calculateL2TokenAddress(L1_USDC), L2_USDC, "Invalid usdc address"); + } + + function test_calculateL2TokenAddress_NotUSDC() public { + address randomToken = makeAddr("randomToken"); + assertEq(l1Gateway.calculateL2TokenAddress(randomToken), address(0), "Invalid usdc address"); + } + + function test_initialize() public { + L1USDCGateway gateway = new L1USDCGateway(); + gateway.initialize(l2Gateway, router, inbox, L1_USDC, L2_USDC, owner); + + assertEq(gateway.counterpartGateway(), l2Gateway, "Invalid counterpartGateway"); + assertEq(gateway.router(), router, "Invalid router"); + assertEq(gateway.inbox(), inbox, "Invalid inbox"); + assertEq(gateway.l1USDC(), L1_USDC, "Invalid L1_USDC"); + assertEq(gateway.l2USDC(), L2_USDC, "Invalid L2_USDC"); + assertEq(gateway.owner(), owner, "Invalid owner"); + assertEq(gateway.depositsPaused(), false, "Invalid depositPaused"); + assertEq(gateway.burner(), address(0), "Invalid burner"); + } + + function test_initialize_revert_InvalidL1USDC() public { + L1USDCGateway gateway = new L1USDCGateway(); + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_InvalidL1USDC.selector)); + gateway.initialize(l2Gateway, router, inbox, address(0), L2_USDC, owner); + } + + function test_initialize_revert_InvalidL2USDC() public { + L1USDCGateway gateway = new L1USDCGateway(); + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_InvalidL2USDC.selector)); + gateway.initialize(l2Gateway, router, inbox, L1_USDC, address(0), owner); + } + + function test_initialize_revert_InvalidOwner() public { + L1USDCGateway gateway = new L1USDCGateway(); + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_InvalidOwner.selector)); + gateway.initialize(l2Gateway, router, inbox, L1_USDC, L2_USDC, address(0)); + } + + function test_initialize_revert_AlreadyInit() public { + L1USDCGateway gateway = new L1USDCGateway(); + gateway.initialize(l2Gateway, router, inbox, L1_USDC, L2_USDC, owner); + vm.expectRevert("ALREADY_INIT"); + gateway.initialize(l2Gateway, router, inbox, L1_USDC, L2_USDC, owner); + } + + function test_finalizeInboundTransfer() public override { + uint256 withdrawalAmount = 100_000_000; + deal(L1_USDC, address(l1Gateway), withdrawalAmount); + + // snapshot state before + uint256 userBalanceBefore = ERC20(L1_USDC).balanceOf(user); + uint256 l1GatewayBalanceBefore = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + + // withdrawal params + address from = address(3000); + uint256 exitNum = 7; + bytes memory callHookData = ""; + bytes memory data = abi.encode(exitNum, callHookData); + + InboxMock(address(inbox)).setL2ToL1Sender(l2Gateway); + + // trigger withdrawal + vm.prank(address(IInbox(l1Gateway.inbox()).bridge())); + l1Gateway.finalizeInboundTransfer(L1_USDC, from, user, withdrawalAmount, data); + + // check tokens are properly released + uint256 userBalanceAfter = ERC20(L1_USDC).balanceOf(user); + assertEq(userBalanceAfter - userBalanceBefore, withdrawalAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceBefore - l1GatewayBalanceAfter, + withdrawalAmount, + "Wrong l1 gateway balance" + ); + } + + function test_outboundTransfer() public virtual override { + // fund user + uint256 depositAmount = 300_555; + deal(L1_USDC, user, depositAmount); + vm.deal(router, retryableCost); + + // snapshot state before + uint256 userBalanceBefore = ERC20(L1_USDC).balanceOf(user); + uint256 l1GatewayBalanceBefore = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + + // approve token + vm.prank(user); + ERC20(L1_USDC).approve(address(l1Gateway), depositAmount); + + // prepare data + bytes memory callHookData = ""; + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + + // event checkers + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(user, user); + + vm.expectEmit(true, true, true, true); + emit InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + l1Gateway.getOutboundCalldata(L1_USDC, user, user, depositAmount, callHookData) + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(L1_USDC, user, user, 0, depositAmount); + + // trigger deposit + vm.prank(router); + bytes memory seqNum0 = l1Gateway.outboundTransfer{value: retryableCost}( + L1_USDC, user, depositAmount, maxGas, gasPriceBid, routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = ERC20(L1_USDC).balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + + assertEq(seqNum0, abi.encode(0), "Invalid seqNum0"); + } + + function test_outboundTransferCustomRefund() public virtual { + // fund user + uint256 depositAmount = 5_500_000_555; + deal(L1_USDC, user, depositAmount); + vm.deal(router, retryableCost); + + // snapshot state before + uint256 userBalanceBefore = ERC20(L1_USDC).balanceOf(user); + uint256 l1GatewayBalanceBefore = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + + // approve token + vm.prank(user); + ERC20(L1_USDC).approve(address(l1Gateway), depositAmount); + + // prepare data + bytes memory callHookData = ""; + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + + // event checkers + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(creditBackAddress, user); + + vm.expectEmit(true, true, true, true); + emit InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + l1Gateway.getOutboundCalldata(L1_USDC, user, user, depositAmount, callHookData) + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(L1_USDC, user, user, 0, depositAmount); + + // trigger deposit + vm.prank(router); + bytes memory seqNum0 = l1Gateway.outboundTransferCustomRefund{value: retryableCost}( + L1_USDC, creditBackAddress, user, depositAmount, maxGas, gasPriceBid, routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = ERC20(L1_USDC).balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = ERC20(L1_USDC).balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + + assertEq(seqNum0, abi.encode(0), "Invalid seqNum0"); + } + + function test_outboundTransfer_revert_DepositsPaused() public { + vm.deal(router, retryableCost); + + vm.prank(owner); + usdcGateway.pauseDeposits(); + + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_DepositsPaused.selector)); + vm.prank(router); + + l1Gateway.outboundTransferCustomRefund{value: retryableCost}( + L1_USDC, creditBackAddress, user, 100, maxGas, gasPriceBid, "" + ); + } + + function test_outboundTransferCustomRefund_revert_DepositsPaused() public { + vm.deal(router, retryableCost); + + vm.prank(owner); + usdcGateway.pauseDeposits(); + + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_DepositsPaused.selector)); + vm.prank(router); + + l1Gateway.outboundTransferCustomRefund{value: retryableCost}( + L1_USDC, creditBackAddress, user, 200, maxGas, gasPriceBid, "" + ); + } + + function test_pauseDeposits() public { + assertEq(usdcGateway.depositsPaused(), false, "Invalid depositPaused"); + + /// expect events + vm.expectEmit(true, true, true, true); + emit DepositsPaused(); + + /// pause it + vm.prank(owner); + usdcGateway.pauseDeposits(); + + /// checks + assertEq(usdcGateway.depositsPaused(), true, "Invalid depositPaused"); + } + + function test_pauseDeposits_revert_NotOwner() public { + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_NotOwner.selector)); + usdcGateway.pauseDeposits(); + } + + function test_pauseDeposits_revert_DepositsAlreadyPaused() public { + vm.prank(owner); + usdcGateway.pauseDeposits(); + + vm.prank(owner); + vm.expectRevert( + abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_DepositsAlreadyPaused.selector) + ); + usdcGateway.pauseDeposits(); + } + + function test_setBurner() public { + address newBurner = makeAddr("new-burner"); + vm.expectEmit(true, true, true, true); + emit BurnerSet(newBurner); + + vm.prank(owner); + usdcGateway.setBurner(newBurner); + + assertEq(usdcGateway.burner(), newBurner, "Invalid burner"); + } + + function test_setBurner_revert_NotOwner() public { + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_NotOwner.selector)); + usdcGateway.setBurner(address(0)); + } + + function test_setBurnAmount() public { + uint256 amount = 100; + + vm.expectEmit(true, true, true, true); + emit BurnAmountSet(amount); + + vm.prank(owner); + usdcGateway.setBurnAmount(amount); + + assertEq(usdcGateway.burnAmount(), amount, "Invalid burnAmount"); + } + + function test_setBurnAmount_revert_NotOwner() public { + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_NotOwner.selector)); + usdcGateway.setBurnAmount(100); + } + + function test_setOwner() public { + address newOwner = makeAddr("new-owner"); + vm.prank(owner); + usdcGateway.setOwner(newOwner); + + assertEq(usdcGateway.owner(), newOwner, "Invalid owner"); + } + + function test_setOwner_revert_InvalidOwner() public { + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_InvalidOwner.selector)); + vm.prank(owner); + usdcGateway.setOwner(address(0)); + } + + function test_setOwner_revert_NotOwner() public { + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_NotOwner.selector)); + usdcGateway.setOwner(owner); + } + + function test_unpauseDeposits() public { + vm.prank(owner); + usdcGateway.pauseDeposits(); + assertEq(usdcGateway.depositsPaused(), true, "Invalid depositPaused"); + + vm.expectEmit(true, true, true, true); + emit DepositsUnpaused(); + + vm.prank(owner); + usdcGateway.unpauseDeposits(); + + assertEq(usdcGateway.depositsPaused(), false, "Invalid depositPaused"); + } + + function test_unpauseDeposits_revert_NotOwner() public { + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_NotOwner.selector)); + usdcGateway.unpauseDeposits(); + } + + function test_unpauseDeposits_revert_DepositsAlreadyUnpaused() public { + vm.prank(owner); + vm.expectRevert( + abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_DepositsAlreadyUnpaused.selector) + ); + usdcGateway.unpauseDeposits(); + } + + //// + // Event declarations + //// + event DepositsPaused(); + event DepositsUnpaused(); + event GatewayUsdcBurned(uint256 amount); + event BurnerSet(address indexed burner); + event BurnAmountSet(uint256 amount); + + event TicketData(uint256 maxSubmissionCost); + event RefundAddresses(address excessFeeRefundAddress, address callValueRefundAddress); + event InboxRetryableTicket(address from, address to, uint256 value, uint256 maxGas, bytes data); + event DepositInitiated( + address l1Token, + address indexed _from, + address indexed _to, + uint256 indexed _sequenceNumber, + uint256 _amount + ); +} + +contract MockUsdc is ERC20 { + constructor() ERC20("USD Coin", "USDC") { + _mint(msg.sender, 1_000_000 ether); + } + + function burn(uint256 _amount) external { + _burn(msg.sender, _amount); + } +} diff --git a/test-foundry/L2AtomicTokenBridgeFactory.t.sol b/test-foundry/L2AtomicTokenBridgeFactory.t.sol index b02da64264..b6414ffe34 100644 --- a/test-foundry/L2AtomicTokenBridgeFactory.t.sol +++ b/test-foundry/L2AtomicTokenBridgeFactory.t.sol @@ -23,8 +23,6 @@ import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import "forge-std/console.sol"; - contract L2AtomicTokenBridgeFactoryTest is Test { L2AtomicTokenBridgeFactory public l2Factory; address public deployer = makeAddr("deployer"); diff --git a/test-foundry/L2USDCGateway.t.sol b/test-foundry/L2USDCGateway.t.sol new file mode 100644 index 0000000000..09102a2474 --- /dev/null +++ b/test-foundry/L2USDCGateway.t.sol @@ -0,0 +1,474 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import "./L2ArbitrumGateway.t.sol"; + +import "contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol"; +import {L1USDCGateway} from "contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol"; +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {AddressAliasHelper} from "contracts/tokenbridge/libraries/AddressAliasHelper.sol"; +import {L2GatewayToken} from "contracts/tokenbridge/libraries/L2GatewayToken.sol"; +import {IFiatToken} from "contracts/tokenbridge/libraries/IFiatToken.sol"; + +contract L2USDCGatewayTest is L2ArbitrumGatewayTest { + L2USDCGateway public l2USDCGateway; + address public l1USDC = makeAddr("l1USDC"); + address public l2USDC; + address public user = makeAddr("usdc_user"); + address public gatewayOwner = makeAddr("l2gw-owner"); + address public usdcOwner = makeAddr("usdc-owner"); + address public usdcProxyAdmin = makeAddr("usdcProxyAdmin"); + address public masterMinter = makeAddr("masterMinter"); + + function setUp() public virtual { + l2USDCGateway = new L2USDCGateway(); + l2Gateway = L2ArbitrumGateway(address(l2USDCGateway)); + + address bridgedUsdcLogic = _deployBridgedUsdcToken(); + vm.prank(usdcProxyAdmin); + l2USDC = _deployUsdcProxy(bridgedUsdcLogic); + + vm.startPrank(usdcOwner); + IFiatToken(l2USDC).initialize( + "USDC token", + "USDC.e", + "USD", + uint8(6), + masterMinter, + makeAddr("newPauser"), + makeAddr("newBlacklister"), + usdcOwner + ); + IFiatToken(l2USDC).initializeV2("USDC"); + IFiatToken(l2USDC).initializeV2_1(makeAddr("lostAndFound")); + IFiatToken(l2USDC).initializeV2_2(new address[](0), "USDC.e"); + vm.stopPrank(); + + vm.prank(masterMinter); + IFiatToken(l2USDC).configureMinter(address(l2USDCGateway), type(uint256).max); + + vm.prank(gatewayOwner); + l2USDCGateway.initialize(l1Counterpart, router, l1USDC, l2USDC, gatewayOwner); + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + + assertEq(IFiatToken(l2USDC).owner(), usdcOwner, "Invalid owner"); + assertEq(IFiatTokenProxy(l2USDC).admin(), usdcProxyAdmin, "Invalid proxyAdmin"); + } + + /* solhint-disable func-name-mixedcase */ + + function test_calculateL2TokenAddress() public { + assertEq(l2USDCGateway.calculateL2TokenAddress(l1USDC), l2USDC, "Invalid address"); + } + + function test_calculateL2TokenAddress_NotUSDC() public { + address randomToken = makeAddr("randomToken"); + assertEq(l2USDCGateway.calculateL2TokenAddress(randomToken), address(0), "Invalid address"); + } + + function test_finalizeInboundTransfer() public override { + vm.deal(address(l2USDCGateway), 100 ether); + + /// events + vm.expectEmit(true, true, true, true); + emit DepositFinalized(l1USDC, sender, receiver, amount); + + /// finalize deposit + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2USDCGateway.finalizeInboundTransfer( + l1USDC, sender, receiver, amount, abi.encode(new bytes(0), new bytes(0)) + ); + + /// check tokens have been minted to receiver + assertEq(ERC20(l2USDC).balanceOf(receiver), amount, "Invalid receiver balance"); + } + + function test_finalizeInboundTransfer_WithCallHook() public override { + vm.deal(address(l2USDCGateway), 100 ether); + + /// events + vm.expectEmit(true, true, true, true); + emit DepositFinalized(l1USDC, sender, receiver, amount); + + /// finalize deposit + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2USDCGateway.finalizeInboundTransfer( + l1USDC, sender, receiver, amount, abi.encode(new bytes(0), new bytes(0x1)) + ); + + /// check tokens have been minted to receiver + assertEq(ERC20(l2USDC).balanceOf(receiver), amount, "Invalid receiver balance"); + } + + function test_finalizeInboundTransfer_ShouldHalt() public { + address notl1USDC = makeAddr("notl1USDC"); + + // check that withdrawal is triggered occurs when deposit is halted + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(notl1USDC, address(l2USDCGateway), sender, 0, 0, amount); + + vm.deal(address(l2USDCGateway), 100 ether); + + /// finalize deposit + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2USDCGateway.finalizeInboundTransfer( + notl1USDC, sender, receiver, amount, abi.encode(new bytes(0), new bytes(0)) + ); + } + + function test_initialize() public { + L2USDCGateway gateway = new L2USDCGateway(); + L2USDCGateway(gateway).initialize(l1Counterpart, router, l1USDC, l2USDC, gatewayOwner); + + assertEq(gateway.counterpartGateway(), l1Counterpart, "Invalid counterpartGateway"); + assertEq(gateway.router(), router, "Invalid router"); + assertEq(gateway.l1USDC(), l1USDC, "Invalid l1USDC"); + assertEq(gateway.l2USDC(), l2USDC, "Invalid l2USDC"); + assertEq(gateway.owner(), gatewayOwner, "Invalid owner"); + } + + function test_initialize_revert_InvalidL1USDC() public { + L2USDCGateway gateway = new L2USDCGateway(); + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_InvalidL1USDC.selector)); + L2USDCGateway(gateway).initialize(l1Counterpart, router, address(0), l2USDC, gatewayOwner); + } + + function test_initialize_revert_InvalidL2USDC() public { + L2USDCGateway gateway = new L2USDCGateway(); + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_InvalidL2USDC.selector)); + L2USDCGateway(gateway).initialize(l1Counterpart, router, l1USDC, address(0), gatewayOwner); + } + + function test_initialize_revert_AlreadyInit() public { + L2USDCGateway gateway = new L2USDCGateway(); + L2USDCGateway(gateway).initialize(l1Counterpart, router, l1USDC, l2USDC, gatewayOwner); + vm.expectRevert("ALREADY_INIT"); + L2USDCGateway(gateway).initialize(l1Counterpart, router, l1USDC, l2USDC, gatewayOwner); + } + + function test_initialize_revert_InvalidOwner() public { + L2USDCGateway gateway = new L2USDCGateway(); + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_InvalidOwner.selector)); + gateway.initialize(l1Counterpart, router, l1USDC, l2USDC, address(0)); + } + + function test_outboundTransfer() public override { + // mint token to user + vm.prank(address(l2USDCGateway)); + IFiatToken(l2USDC).mint(sender, 20 ether); + + // withdrawal params + uint256 withdrawalAmount = 200_500; + bytes memory data = new bytes(0); + + // approve withdrawal + vm.prank(sender); + IERC20(l2USDC).approve(address(l2USDCGateway), withdrawalAmount); + + // events + uint256 expectedId = 0; + bytes memory expectedData = + l2USDCGateway.getOutboundCalldata(l1USDC, sender, receiver, withdrawalAmount, data); + vm.expectEmit(true, true, true, true); + emit TxToL1(sender, l1Counterpart, expectedId, expectedData); + + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1USDC, sender, receiver, expectedId, 0, withdrawalAmount); + + // withdraw + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(sender); + l2USDCGateway.outboundTransfer(l1USDC, receiver, withdrawalAmount, 0, 0, data); + } + + function test_outboundTransfer_4Args() public override { + // mint token to user + vm.prank(address(l2USDCGateway)); + IFiatToken(l2USDC).mint(sender, 20 ether); + + // withdrawal params + uint256 withdrawalAmount = 200_500; + bytes memory data = new bytes(0); + + // approve withdrawal + vm.prank(sender); + IERC20(l2USDC).approve(address(l2USDCGateway), withdrawalAmount); + + // events + uint256 expectedId = 0; + bytes memory expectedData = + l2USDCGateway.getOutboundCalldata(l1USDC, sender, receiver, withdrawalAmount, data); + vm.expectEmit(true, true, true, true); + emit TxToL1(sender, l1Counterpart, expectedId, expectedData); + + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1USDC, sender, receiver, expectedId, 0, withdrawalAmount); + + // withdraw + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(sender); + l2USDCGateway.outboundTransfer(l1USDC, receiver, withdrawalAmount, data); + } + + function test_outboundTransfer_revert_WithdrawalsPaused() public { + // pause withdrawals + vm.prank(gatewayOwner); + l2USDCGateway.pauseWithdrawals(); + + vm.expectRevert( + abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_WithdrawalsPaused.selector) + ); + l2USDCGateway.outboundTransfer(l1USDC, receiver, 200, 0, 0, new bytes(0)); + } + + function test_outboundTransfer_revert_NotExpectedL1Token() public override { + // TODO + } + + function test_pauseWithdrawals() public { + assertEq(l2USDCGateway.withdrawalsPaused(), false, "Invalid withdrawalsPaused"); + + uint256 mockL2Supply = 5000 ether; + vm.mockCall( + address(l2USDC), abi.encodeWithSignature("totalSupply()"), abi.encode(mockL2Supply) + ); + + // events + vm.expectEmit(true, true, true, true); + emit WithdrawalsPaused(); + + // pause withdrawals + vm.prank(gatewayOwner); + l2USDCGateway.pauseWithdrawals(); + + // checks + assertEq(l2USDCGateway.withdrawalsPaused(), true, "Invalid withdrawalsPaused"); + } + + function test_pauseWithdrawals_revert_WithdrawalsAlreadyPaused() public { + vm.startPrank(gatewayOwner); + l2USDCGateway.pauseWithdrawals(); + + vm.expectRevert( + abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_WithdrawalsAlreadyPaused.selector) + ); + l2USDCGateway.pauseWithdrawals(); + } + + function test_pauseWithdrawals_revert_NotOwner() public { + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_NotOwner.selector)); + l2USDCGateway.pauseWithdrawals(); + } + + function test_setOwner() public { + address newOwner = makeAddr("new-owner"); + + vm.expectEmit(true, true, true, true); + emit OwnerSet(newOwner); + + vm.prank(gatewayOwner); + l2USDCGateway.setOwner(newOwner); + + assertEq(l2USDCGateway.owner(), newOwner, "Invalid owner"); + } + + function test_setOwner_revert_InvalidOwner() public { + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_InvalidOwner.selector)); + vm.prank(gatewayOwner); + l2USDCGateway.setOwner(address(0)); + } + + function test_setOwner_revert_NotOwner() public { + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_NotOwner.selector)); + l2USDCGateway.setOwner(gatewayOwner); + } + + function test_setUsdcOwnershipTransferrer() public { + assertEq( + l2USDCGateway.usdcOwnershipTransferrer(), address(0), "Invalid usdcOwnershipTransferrer" + ); + + address transferrer = makeAddr("transferrer"); + + vm.expectEmit(true, true, true, true); + emit USDCOwnershipTransferrerSet(transferrer); + + vm.prank(gatewayOwner); + l2USDCGateway.setUsdcOwnershipTransferrer(transferrer); + + assertEq( + l2USDCGateway.usdcOwnershipTransferrer(), + transferrer, + "Invalid usdcOwnershipTransferrer" + ); + } + + function test_setUsdcOwnershipTransferrer_revert_NotOwner() public { + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_NotOwner.selector)); + l2USDCGateway.setUsdcOwnershipTransferrer(makeAddr("rand")); + } + + function test_transferUSDCRoles() public { + // set the transferrer + address transferrer = makeAddr("transferrer"); + vm.prank(gatewayOwner); + l2USDCGateway.setUsdcOwnershipTransferrer(transferrer); + + // transfer ownership to gateway + vm.prank(usdcOwner); + IFiatToken(l2USDC).transferOwnership(address(l2USDCGateway)); + + // transfer proxy admin to gateway + vm.prank(usdcProxyAdmin); + IFiatTokenProxy(l2USDC).changeAdmin(address(l2USDCGateway)); + + assertEq(IFiatToken(l2USDC).owner(), address(l2USDCGateway), "Invalid owner"); + assertEq(IFiatTokenProxy(l2USDC).admin(), address(l2USDCGateway), "Invalid proxyAdmin"); + + address newTokenOwner = makeAddr("new-token-owner"); + + // events + vm.expectEmit(true, true, true, true); + emit USDCOwnershipTransferred(newTokenOwner, transferrer); + + // transferUSDCRoles + vm.prank(transferrer); + l2USDCGateway.transferUSDCRoles(newTokenOwner); + + // checks + assertEq(IFiatToken(l2USDC).owner(), newTokenOwner, "Invalid owner"); + assertEq(IFiatTokenProxy(l2USDC).admin(), transferrer, "Invalid proxyAdmin"); + } + + function test_transferUSDCRoles_revert_NotUSDCOwnershipTransferrer() public { + vm.expectRevert( + abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_NotUSDCOwnershipTransferrer.selector) + ); + l2USDCGateway.transferUSDCRoles(makeAddr("rand")); + } + + function test_unpauseWithdrawals() public { + // pause withdrawals + vm.prank(gatewayOwner); + l2USDCGateway.pauseWithdrawals(); + assertEq(l2USDCGateway.withdrawalsPaused(), true, "Invalid withdrawalsPaused"); + + // events + vm.expectEmit(true, true, true, true); + emit WithdrawalsUnpaused(); + + // unpause withdrawals + vm.prank(gatewayOwner); + l2USDCGateway.unpauseWithdrawals(); + + // checks + assertEq(l2USDCGateway.withdrawalsPaused(), false, "Invalid withdrawalsPaused"); + } + + function test_unpauseWithdrawals_revert_NotOwner() public { + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_NotOwner.selector)); + l2USDCGateway.unpauseWithdrawals(); + } + + function test_unpauseWithdrawals_revert_AlreadyUnpaused() public { + vm.prank(gatewayOwner); + vm.expectRevert( + abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_WithdrawalsAlreadyUnpaused.selector) + ); + l2USDCGateway.unpauseWithdrawals(); + } + + //// + // Event declarations + //// + event WithdrawalsPaused(); + event WithdrawalsUnpaused(); + event OwnerSet(address indexed owner); + event USDCOwnershipTransferrerSet(address indexed usdcOwnershipTransferrer); + event USDCOwnershipTransferred(address indexed newOwner, address indexed newProxyAdmin); + + function _deployBridgedUsdcToken() public returns (address) { + /// deploy library + address sigCheckerAddress = _deployBytecodeFromJSON( + "/node_modules/@offchainlabs/stablecoin-evm/artifacts/hardhat/contracts/util/SignatureChecker.sol/SignatureChecker.json" + ); + require(sigCheckerAddress != address(0), "Failed to deploy contract"); + + /// deploy bridged usdc token + + // insert lib address into bytecode + bytes memory b1 = + hex"60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b614aec80620000676000396000f3fe608060405234801561001057600080fd5b506004361061036d5760003560e01c80638456cb59116101d3578063b7b7289911610104578063e3ee160e116100a2578063ef55bec61161007c578063ef55bec614610f9c578063f2fde38b14610ffb578063f9f92be414611021578063fe575a87146110475761036d565b8063e3ee160e14610f09578063e5a6b10f14610f68578063e94a010214610f705761036d565b8063d505accf116100de578063d505accf14610e12578063d608ea6414610e63578063d916948714610ed3578063dd62ed3e14610edb5761036d565b8063b7b7289914610c78578063bd10243014610d33578063cf09299514610d3b5761036d565b8063a0cc6a6811610171578063aa20e1e41161014b578063aa20e1e414610bd0578063aa271e1a14610bf6578063ad38bf2214610c1c578063b2118a8d14610c425761036d565b8063a0cc6a6814610b70578063a457c2d714610b78578063a9059cbb14610ba45761036d565b80638da5cb5b116101ad5780638da5cb5b14610a8d57806395d89b4114610a955780639fd0506d14610a9d5780639fd5a6cf14610aa55761036d565b80638456cb591461098857806388b7ab63146109905780638a6db9c314610a675761036d565b806338a63183116102ad57806354fd4d501161024b5780635c975abb116102255780635c975abb1461092c57806370a08231146109345780637ecebe001461095a5780637f2eecc3146109805761036d565b806354fd4d50146108bd578063554bab3c146108c55780635a049a70146108eb5761036d565b806340c10f191161028757806340c10f191461078657806342966c68146107b2578063430239b4146107cf5780634e44d956146108915761036d565b806338a631831461074a57806339509351146107525780633f4ba83a1461077e5761036d565b80632fc81e091161031a578063313ce567116102f4578063313ce567146105215780633357162b1461053f57806335d99f351461071e5780633644e515146107425761036d565b80632fc81e09146104cd5780633092afd5146104f357806330adf81f146105195761036d565b80631a8952661161034b5780631a8952661461044957806323b872dd146104715780632ab60045146104a75761036d565b806306fdde0314610372578063095ea7b3146103ef57806318160ddd1461042f575b600080fd5b61037a61106d565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103b457818101518382015260200161039c565b50505050905090810190601f1680156103e15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61041b6004803603604081101561040557600080fd5b506001600160a01b038135169060200135611119565b604080519115158252519081900360200190f35b61043761118f565b60408051918252519081900360200190f35b61046f6004803603602081101561045f57600080fd5b50356001600160a01b0316611195565b005b61041b6004803603606081101561048757600080fd5b506001600160a01b0381358116916020810135909116906040013561121e565b61046f600480360360208110156104bd57600080fd5b50356001600160a01b031661141f565b61046f600480360360208110156104e357600080fd5b50356001600160a01b0316611525565b61041b6004803603602081101561050957600080fd5b50356001600160a01b031661156f565b610437611616565b61052961163a565b6040805160ff9092168252519081900360200190f35b61046f600480360361010081101561055657600080fd5b81019060208101813564010000000081111561057157600080fd5b82018360208201111561058357600080fd5b803590602001918460018302840111640100000000831117156105a557600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156105f857600080fd5b82018360208201111561060a57600080fd5b8035906020019184600183028401116401000000008311171561062c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561067f57600080fd5b82018360208201111561069157600080fd5b803590602001918460018302840111640100000000831117156106b357600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff1692505060208101356001600160a01b0390811691604081013582169160608201358116916080013516611643565b610726611882565b604080516001600160a01b039092168252519081900360200190f35b610437611891565b6107266118a0565b61041b6004803603604081101561076857600080fd5b506001600160a01b0381351690602001356118af565b61046f61191c565b61041b6004803603604081101561079c57600080fd5b506001600160a01b0381351690602001356119b8565b61046f600480360360208110156107c857600080fd5b5035611c9b565b61046f600480360360408110156107e557600080fd5b81019060208101813564010000000081111561080057600080fd5b82018360208201111561081257600080fd5b8035906020019184602083028401116401000000008311171561083457600080fd5b91939092909160208101903564010000000081111561085257600080fd5b82018360208201111561086457600080fd5b8035906020019184600183028401116401000000008311171561088657600080fd5b509092509050611eaa565b61041b600480360360408110156108a757600080fd5b506001600160a01b038135169060200135611fe4565b61037a6120fa565b61046f600480360360208110156108db57600080fd5b50356001600160a01b0316612131565b61046f600480360360a081101561090157600080fd5b506001600160a01b038135169060208101359060ff604082013516906060810135906080013561223d565b61041b6122b0565b6104376004803603602081101561094a57600080fd5b50356001600160a01b03166122c0565b6104376004803603602081101561097057600080fd5b50356001600160a01b03166122d1565b6104376122ec565b61046f612310565b61046f600480360360e08110156109a657600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c08201356401000000008111156109f257600080fd5b820183602082011115610a0457600080fd5b80359060200191846001830284011164010000000083111715610a2657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506123b2945050505050565b61043760048036036020811015610a7d57600080fd5b50356001600160a01b03166124b7565b6107266124d2565b61037a6124e1565b61072661255a565b61046f600480360360a0811015610abb57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610afb57600080fd5b820183602082011115610b0d57600080fd5b80359060200191846001830284011164010000000083111715610b2f57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612569945050505050565b6104376125d5565b61041b60048036036040811015610b8e57600080fd5b506001600160a01b0381351690602001356125f9565b61041b60048036036040811015610bba57600080fd5b506001600160a01b038135169060200135612666565b61046f60048036036020811015610be657600080fd5b50356001600160a01b031661276a565b61041b60048036036020811015610c0c57600080fd5b50356001600160a01b0316612876565b61046f60048036036020811015610c3257600080fd5b50356001600160a01b0316612894565b61046f60048036036060811015610c5857600080fd5b506001600160a01b038135811691602081013590911690604001356129a0565b61046f60048036036060811015610c8e57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135640100000000811115610cbe57600080fd5b820183602082011115610cd057600080fd5b80359060200191846001830284011164010000000083111715610cf257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612a02945050505050565b610726612a6c565b61046f600480360360e0811015610d5157600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610d9d57600080fd5b820183602082011115610daf57600080fd5b80359060200191846001830284011164010000000083111715610dd157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612a7b945050505050565b61046f600480360360e0811015610e2857600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612b75565b61046f60048036036020811015610e7957600080fd5b810190602081018135640100000000811115610e9457600080fd5b820183602082011115610ea657600080fd5b80359060200191846001830284011164010000000083111715610ec857600080fd5b509092509050612bec565b610437612ca6565b61043760048036036040811015610ef157600080fd5b506001600160a01b0381358116916020013516612cca565b61046f6004803603610120811015610f2057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135612cf5565b61037a612dfe565b61041b60048036036040811015610f8657600080fd5b506001600160a01b038135169060200135612e77565b61046f6004803603610120811015610fb357600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135612ea2565b61046f6004803603602081101561101157600080fd5b50356001600160a01b0316612f9e565b61046f6004803603602081101561103757600080fd5b50356001600160a01b0316613096565b61041b6004803603602081101561105d57600080fd5b50356001600160a01b031661311f565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111115780601f106110e657610100808354040283529160200191611111565b820191906000526020600020905b8154815290600101906020018083116110f457829003601f168201915b505050505081565b600154600090600160a01b900460ff161561117b576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61118633848461312a565b50600192915050565b600b5490565b6002546001600160a01b031633146111de5760405162461bcd60e51b815260040180806020018281038252602c815260200180614768602c913960400191505060405180910390fd5b6111e781613216565b6040516001600160a01b038216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b600154600090600160a01b900460ff1615611280576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3361128a81613221565b156112c65760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b846112d081613221565b1561130c5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b8461131681613221565b156113525760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6001600160a01b0387166000908152600a602090815260408083203384529091529020548511156113b45760405162461bcd60e51b81526004018080602001828103825260288152602001806148586028913960400191505060405180910390fd5b6113bf878787613242565b6001600160a01b0387166000908152600a602090815260408083203384529091529020546113ed908661338b565b6001600160a01b0388166000908152600a60209081526040808320338452909152902055600193505050509392505050565b6000546001600160a01b0316331461147e576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166114c35760405162461bcd60e51b815260040180806020018281038252602a8152602001806146a1602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461153757600080fd5b6000611542306133e8565b9050801561155557611555308383613242565b61155e30613425565b50506012805460ff19166002179055565b6008546000906001600160a01b031633146115bb5760405162461bcd60e51b815260040180806020018281038252602981526020018061473f6029913960400191505060405180910390fd5b6001600160a01b0382166000818152600c60209081526040808320805460ff19169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b600854600160a01b900460ff161561168c5760405162461bcd60e51b815260040180806020018281038252602a8152602001806148d3602a913960400191505060405180910390fd5b6001600160a01b0384166116d15760405162461bcd60e51b815260040180806020018281038252602f815260200180614805602f913960400191505060405180910390fd5b6001600160a01b0383166117165760405162461bcd60e51b81526004018080602001828103825260298152602001806146786029913960400191505060405180910390fd5b6001600160a01b03821661175b5760405162461bcd60e51b815260040180806020018281038252602e815260200180614880602e913960400191505060405180910390fd5b6001600160a01b0381166117a05760405162461bcd60e51b81526004018080602001828103825260288152602001806149c06028913960400191505060405180910390fd5b87516117b39060049060208b019061442f565b5086516117c79060059060208a019061442f565b5085516117db90600790602089019061442f565b506006805460ff191660ff8716179055600880547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03878116919091179092556001805482168684161790556002805490911691841691909117905561184a81613430565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b179055505050505050565b6008546001600160a01b031681565b600061189b61346a565b905090565b600e546001600160a01b031690565b600154600090600160a01b900460ff1615611911576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61118633848461355f565b6001546001600160a01b031633146119655760405162461bcd60e51b81526004018080602001828103825260228152602001806149746022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b600154600090600160a01b900460ff1615611a1a576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611a685760405162461bcd60e51b81526004018080602001828103825260218152602001806147e46021913960400191505060405180910390fd5b33611a7281613221565b15611aae5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b83611ab881613221565b15611af45760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6001600160a01b038516611b395760405162461bcd60e51b815260040180806020018281038252602381526020018061460d6023913960400191505060405180910390fd5b60008411611b785760405162461bcd60e51b81526004018080602001828103825260298152602001806146f06029913960400191505060405180910390fd5b336000908152600d602052604090205480851115611bc75760405162461bcd60e51b815260040180806020018281038252602e815260200180614946602e913960400191505060405180910390fd5b600b54611bd4908661359c565b600b55611bf386611bee87611be8836133e8565b9061359c565b6135fd565b611bfd818661338b565b336000818152600d602090815260409182902093909355805188815290516001600160a01b038a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a36040805186815290516001600160a01b038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b600154600160a01b900460ff1615611cfa576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611d485760405162461bcd60e51b81526004018080602001828103825260218152602001806147e46021913960400191505060405180910390fd5b33611d5281613221565b15611d8e5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6000611d99336133e8565b905060008311611dda5760405162461bcd60e51b81526004018080602001828103825260298152602001806145e46029913960400191505060405180910390fd5b82811015611e195760405162461bcd60e51b81526004018080602001828103825260268152602001806147be6026913960400191505060405180910390fd5b600b54611e26908461338b565b600b55611e3733611bee838661338b565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff16600214611ebc57600080fd5b611ec8600583836144ad565b5060005b83811015611fab5760036000868684818110611ee457fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff16611f455760405162461bcd60e51b815260040180806020018281038252603d815260200180614531603d913960400191505060405180910390fd5b611f69858583818110611f5457fe5b905060200201356001600160a01b0316613425565b60036000868684818110611f7957fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff19169055600101611ecc565b50611fb530613425565b5050306000908152600360208190526040909120805460ff199081169091556012805490911690911790555050565b600154600090600160a01b900460ff1615612046576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6008546001600160a01b0316331461208f5760405162461bcd60e51b815260040180806020018281038252602981526020018061473f6029913960400191505060405180910390fd5b6001600160a01b0383166000818152600c60209081526040808320805460ff19166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b6000546001600160a01b03163314612190576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166121d55760405162461bcd60e51b81526004018080602001828103825260288152602001806145916028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b600154600160a01b900460ff161561229c576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6122a985858585856136bd565b5050505050565b600154600160a01b900460ff1681565b60006122cb826133e8565b92915050565b6001600160a01b031660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b6001546001600160a01b031633146123595760405162461bcd60e51b81526004018080602001828103825260228152602001806149746022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b1790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b600154600160a01b900460ff1615612411576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8661241b81613221565b156124575760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b8661246181613221565b1561249d5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6124ac898989898989896136fd565b505050505050505050565b6001600160a01b03166000908152600d602052604090205490565b6000546001600160a01b031690565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111115780601f106110e657610100808354040283529160200191611111565b6001546001600160a01b031681565b600154600160a01b900460ff16156125c8576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6122a985858585856137ea565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b600154600090600160a01b900460ff161561265b576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611186338484613a60565b600154600090600160a01b900460ff16156126c8576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336126d281613221565b1561270e5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b8361271881613221565b156127545760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b61275f338686613242565b506001949350505050565b6000546001600160a01b031633146127c9576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03811661280e5760405162461bcd60e51b815260040180806020018281038252602f815260200180614805602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b6001600160a01b03166000908152600c602052604090205460ff1690565b6000546001600160a01b031633146128f3576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166129385760405162461bcd60e51b8152600401808060200182810382526032815260200180614a166032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e546001600160a01b031633146129e95760405162461bcd60e51b81526004018080602001828103825260248152602001806148346024913960400191505060405180910390fd5b6129fd6001600160a01b0384168383613aaf565b505050565b600154600160a01b900460ff1615612a61576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6129fd838383613b2f565b6002546001600160a01b031681565b600154600160a01b900460ff1615612ada576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612ae481613221565b15612b205760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b86612b2a81613221565b15612b665760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6124ac89898989898989613c01565b600154600160a01b900460ff1615612bd4576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612be387878787878787613c92565b50505050505050565b600854600160a01b900460ff168015612c08575060125460ff16155b612c1157600080fd5b612c1d600483836144ad565b50612c9282828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f320000000000000000000000000000000000000000000000000000000000000060208201529150613cd49050565b600f5550506012805460ff19166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b600154600160a01b900460ff1615612d54576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88612d5e81613221565b15612d9a5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b88612da481613221565b15612de05760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b612df18b8b8b8b8b8b8b8b8b613cea565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111115780601f106110e657610100808354040283529160200191611111565b6001600160a01b03919091166000908152601060209081526040808320938352929052205460ff1690565b600154600160a01b900460ff1615612f01576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88612f0b81613221565b15612f475760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b88612f5181613221565b15612f8d5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b612df18b8b8b8b8b8b8b8b8b613d2e565b6000546001600160a01b03163314612ffd576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166130425760405162461bcd60e51b81526004018080602001828103825260268152602001806146306026913960400191505060405180910390fd5b600054604080516001600160a01b039283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a161309381613430565b50565b6002546001600160a01b031633146130df5760405162461bcd60e51b815260040180806020018281038252602c815260200180614768602c913960400191505060405180910390fd5b6130e881613425565b6040516001600160a01b038216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b60006122cb82613221565b6001600160a01b03831661316f5760405162461bcd60e51b81526004018080602001828103825260248152602001806149226024913960400191505060405180910390fd5b6001600160a01b0382166131b45760405162461bcd60e51b81526004018080602001828103825260228152602001806146566022913960400191505060405180910390fd5b6001600160a01b038084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b613093816000613d72565b6001600160a01b031660009081526009602052604090205460ff1c60011490565b6001600160a01b0383166132875760405162461bcd60e51b81526004018080602001828103825260258152602001806148fd6025913960400191505060405180910390fd5b6001600160a01b0382166132cc5760405162461bcd60e51b815260040180806020018281038252602381526020018061456e6023913960400191505060405180910390fd5b6132d5836133e8565b8111156133135760405162461bcd60e51b81526004018080602001828103825260268152602001806147196026913960400191505060405180910390fd5b61332a83611bee83613324876133e8565b9061338b565b61333b82611bee83611be8866133e8565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000828211156133e2576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001600160a01b03166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b613093816001613d72565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815260009361189b93919290918301828280156135175780601f106134ec57610100808354040283529160200191613517565b820191906000526020600020905b8154815290600101906020018083116134fa57829003601f168201915b50505050506040518060400160405280600181526020017f320000000000000000000000000000000000000000000000000000000000000081525061355a613de1565b613de5565b6001600160a01b038084166000908152600a60209081526040808320938616835292905220546129fd9084908490613597908561359c565b61312a565b6000828201838110156135f6576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81111561365c5760405162461bcd60e51b815260040180806020018281038252602a815260200180614794602a913960400191505060405180910390fd5b61366582613221565b156136a15760405162461bcd60e51b81526004018080602001828103825260258152602001806146cb6025913960400191505060405180910390fd5b6001600160a01b03909116600090815260096020526040902055565b6122a98585848487604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613b2f565b6001600160a01b03861633146137445760405162461bcd60e51b81526004018080602001828103825260258152602001806148ae6025913960400191505060405180910390fd5b61375087838686613e59565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de86020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e08083018690528351808403909101815261010090920190925280519101206137d590889083613ee5565b6137df878361403c565b612be3878787613242565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214806138185750428210155b613869576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b600061390461387661346a565b6001600160a01b0380891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e090920190528051910120614096565b905073"; + + bytes memory b2 = + hex"636ccea6528783856040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561398457818101518382015260200161396c565b50505050905090810190601f1680156139b15780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b1580156139d057600080fd5b505af41580156139e4573d6000803e3d6000fd5b505050506040513d60208110156139fa57600080fd5b5051613a4d576040805162461bcd60e51b815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b613a5886868661312a565b505050505050565b6129fd838361359784604051806060016040528060258152602001614a92602591396001600160a01b03808a166000908152600a60209081526040808320938c168352929052205491906140d0565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526129fd908490614167565b613b398383614218565b613ba6837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b858560405160200180848152602001836001600160a01b0316815260200182815260200193505050506040516020818303038152906040528051906020012083613ee5565b6001600160a01b0383166000818152601060209081526040808320868452909152808220805460ff19166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b613c0d87838686613e59565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a22676020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e08083018690528351808403909101815261010090920190925280519101206137d590889083613ee5565b612be387878787868689604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526137ea565b600046613ce2848483613de5565b949350505050565b6124ac89898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613c01565b6124ac89898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526136fd565b80613d8557613d80826133e8565b613dc1565b6001600160a01b0382166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b6001600160a01b0390921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b814211613e975760405162461bcd60e51b815260040180806020018281038252602b8152602001806145b9602b913960400191505060405180910390fd5b804210613ed55760405162461bcd60e51b8152600401808060200182810382526025815260200180614a6d6025913960400191505060405180910390fd5b613edf8484614218565b50505050565b73"; + + bytes memory b3 = + hex"636ccea65284613f11613f0b61346a565b86614096565b846040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613f73578181015183820152602001613f5b565b50505050905090810190601f168015613fa05780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015613fbf57600080fd5b505af4158015613fd3573d6000803e3d6000fd5b505050506040513d6020811015613fe957600080fd5b50516129fd576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b0382166000818152601060209081526040808320858452909152808220805460ff19166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6000818484111561415f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561412457818101518382015260200161410c565b50505050905090810190601f1680156141515780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60606141bc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661427f9092919063ffffffff16565b8051909150156129fd578080602001905160208110156141db57600080fd5b50516129fd5760405162461bcd60e51b815260040180806020018281038252602a815260200180614996602a913960400191505060405180910390fd5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff161561427b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806149e8602e913960400191505060405180910390fd5b5050565b6060613ce2848460008585614293856143c3565b6142e4576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061434157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614304565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146143a3576040519150601f19603f3d011682016040523d82523d6000602084013e6143a8565b606091505b50915091506143b88282866143c9565b979650505050505050565b3b151590565b606083156143d85750816135f6565b8251156143e85782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561412457818101518382015260200161410c565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061447057805160ff191683800117855561449d565b8280016001018555821561449d579182015b8281111561449d578251825591602001919060010190614482565b506144a992915061451b565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106144ee5782800160ff1982351617855561449d565b8280016001018555821561449d579182015b8281111561449d578235825591602001919060010190614500565b5b808211156144a9576000815560010161451c56fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212206b5e166c9bb86d4031d11482d2bd231c0f948b4d47fe27594c561c1db6a6c61364736f6c634300060c0033"; + + bytes memory libAddress = abi.encodePacked(sigCheckerAddress); + + bytes memory fullBytecode = bytes.concat( + bytes.concat(bytes.concat(bytes.concat(b1, libAddress), b2), libAddress), b3 + ); + + address bridgedUsdcToken; + assembly { + bridgedUsdcToken := create(0, add(fullBytecode, 0x20), mload(fullBytecode)) + } + require(bridgedUsdcToken != address(0), "Failed to deploy contract"); + return bridgedUsdcToken; + } + + function _deployUsdcProxy(address logic) public returns (address) { + address proxyAddress = _deployBytecodeWithConstructorFromJSON( + "/node_modules/@offchainlabs/stablecoin-evm/artifacts/hardhat/contracts/v1/FiatTokenProxy.sol/FiatTokenProxy.json", + abi.encode(logic) + ); + require(proxyAddress != address(0), "Failed to deploy contract"); + + return proxyAddress; + } + + function _deployBytecode(bytes memory bytecode) public returns (address) { + address addr; + assembly { + addr := create(0, add(bytecode, 0x20), mload(bytecode)) + } + require(addr != address(0), "bytecode deployment failed"); + return addr; + } + + function _deployBytecodeWithConstructor(bytes memory bytecode, bytes memory abiencodedargs) + internal + returns (address) + { + bytes memory bytecodeWithConstructor = bytes.concat(bytecode, abiencodedargs); + return _deployBytecode(bytecodeWithConstructor); + } + + function _deployBytecodeFromJSON(bytes memory path) public returns (address) { + bytes memory bytecode = _getBytecode(path); + return _deployBytecode(bytecode); + } + + function _deployBytecodeWithConstructorFromJSON(bytes memory path, bytes memory abiencodedargs) + internal + returns (address) + { + bytes memory bytecode = _getBytecode(path); + return _deployBytecodeWithConstructor(bytecode, abiencodedargs); + } + + function _getBytecode(bytes memory path) public returns (bytes memory) { + string memory readerBytecodeFilePath = string(abi.encodePacked(vm.projectRoot(), path)); + string memory json = vm.readFile(readerBytecodeFilePath); + try vm.parseJsonBytes(json, ".bytecode.object") returns (bytes memory bytecode) { + return bytecode; + } catch { + return vm.parseJsonBytes(json, ".bytecode"); + } + } +} diff --git a/test/signatures/L1OrbitUSDCGateway b/test/signatures/L1OrbitUSDCGateway new file mode 100644 index 0000000000..b59554ae2a --- /dev/null +++ b/test/signatures/L1OrbitUSDCGateway @@ -0,0 +1,29 @@ +{ + "burnAmount()": "486a7e6b", + "burnLockedUSDC()": "8a5e52bb", + "burner()": "27810b6e", + "calculateL2TokenAddress(address)": "a7e28d48", + "counterpartGateway()": "2db09c1c", + "depositsPaused()": "60da3e83", + "encodeWithdrawal(uint256,address)": "020a6058", + "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", + "getExternalCall(uint256,address,bytes)": "f68a9082", + "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", + "inbox()": "fb0e722b", + "initialize(address,address,address,address,address,address)": "cc2a9a5b", + "l1USDC()": "a6f73669", + "l2USDC()": "29e96f9e", + "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", + "outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)": "4fb1a07b", + "owner()": "8da5cb5b", + "pauseDeposits()": "02191980", + "postUpgradeInit()": "95fcea78", + "redirectedExits(bytes32)": "bcf2e6eb", + "router()": "f887ea40", + "setBurnAmount(uint256)": "cc43f3d3", + "setBurner(address)": "a996d6ce", + "setOwner(address)": "13af4035", + "supportsInterface(bytes4)": "01ffc9a7", + "transferExitAndCall(uint256,address,address,bytes,bytes)": "bd5f3e7d", + "unpauseDeposits()": "63d8882a" +} diff --git a/test/signatures/L1USDCGateway b/test/signatures/L1USDCGateway new file mode 100644 index 0000000000..b59554ae2a --- /dev/null +++ b/test/signatures/L1USDCGateway @@ -0,0 +1,29 @@ +{ + "burnAmount()": "486a7e6b", + "burnLockedUSDC()": "8a5e52bb", + "burner()": "27810b6e", + "calculateL2TokenAddress(address)": "a7e28d48", + "counterpartGateway()": "2db09c1c", + "depositsPaused()": "60da3e83", + "encodeWithdrawal(uint256,address)": "020a6058", + "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", + "getExternalCall(uint256,address,bytes)": "f68a9082", + "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", + "inbox()": "fb0e722b", + "initialize(address,address,address,address,address,address)": "cc2a9a5b", + "l1USDC()": "a6f73669", + "l2USDC()": "29e96f9e", + "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", + "outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)": "4fb1a07b", + "owner()": "8da5cb5b", + "pauseDeposits()": "02191980", + "postUpgradeInit()": "95fcea78", + "redirectedExits(bytes32)": "bcf2e6eb", + "router()": "f887ea40", + "setBurnAmount(uint256)": "cc43f3d3", + "setBurner(address)": "a996d6ce", + "setOwner(address)": "13af4035", + "supportsInterface(bytes4)": "01ffc9a7", + "transferExitAndCall(uint256,address,address,bytes,bytes)": "bd5f3e7d", + "unpauseDeposits()": "63d8882a" +} diff --git a/test/signatures/L2USDCGateway b/test/signatures/L2USDCGateway new file mode 100644 index 0000000000..5873150681 --- /dev/null +++ b/test/signatures/L2USDCGateway @@ -0,0 +1,22 @@ +{ + "calculateL2TokenAddress(address)": "a7e28d48", + "counterpartGateway()": "2db09c1c", + "exitNum()": "015234ab", + "finalizeInboundTransfer(address,address,address,uint256,bytes)": "2e567b36", + "getOutboundCalldata(address,address,address,uint256,bytes)": "a0c76a96", + "initialize(address,address,address,address,address)": "1459457a", + "l1USDC()": "a6f73669", + "l2USDC()": "29e96f9e", + "outboundTransfer(address,address,uint256,bytes)": "7b3a3c8b", + "outboundTransfer(address,address,uint256,uint256,uint256,bytes)": "d2ce7d65", + "owner()": "8da5cb5b", + "pauseWithdrawals()": "56bb54a7", + "postUpgradeInit()": "95fcea78", + "router()": "f887ea40", + "setOwner(address)": "13af4035", + "setUsdcOwnershipTransferrer(address)": "54d3a598", + "transferUSDCRoles(address)": "c689fc34", + "unpauseWithdrawals()": "e4c4be58", + "usdcOwnershipTransferrer()": "77403988", + "withdrawalsPaused()": "e9f2838e" +} diff --git a/test/storage/L1AtomicTokenBridgeCreator b/test/storage/L1AtomicTokenBridgeCreator new file mode 100644 index 0000000000..41f7e032aa --- /dev/null +++ b/test/storage/L1AtomicTokenBridgeCreator @@ -0,0 +1,22 @@ +| Name | Type | Slot | Offset | Bytes | Contract | +|--------------------------------|--------------------------------------------------|------|--------|-------|------------------------------------------------------------------------------------------| +| _initialized | uint8 | 0 | 0 | 1 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| _initializing | bool | 0 | 1 | 1 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| __gap | uint256[50] | 1 | 0 | 1600 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| _owner | address | 51 | 0 | 20 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| __gap | uint256[49] | 52 | 0 | 1568 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| inboxToL1Deployment | mapping(address => struct L1DeploymentAddresses) | 101 | 0 | 32 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| inboxToL2Deployment | mapping(address => struct L2DeploymentAddresses) | 102 | 0 | 32 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| gasLimitForL2FactoryDeployment | uint256 | 103 | 0 | 32 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| retryableSender | contract L1TokenBridgeRetryableSender | 104 | 0 | 20 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| l1Templates | struct L1AtomicTokenBridgeCreator.L1Templates | 105 | 0 | 256 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| l2TokenBridgeFactoryTemplate | address | 113 | 0 | 20 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| l2RouterTemplate | address | 114 | 0 | 20 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| l2StandardGatewayTemplate | address | 115 | 0 | 20 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| l2CustomGatewayTemplate | address | 116 | 0 | 20 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| l2WethGatewayTemplate | address | 117 | 0 | 20 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| l2WethTemplate | address | 118 | 0 | 20 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| l2MulticallTemplate | address | 119 | 0 | 20 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| l1Weth | address | 120 | 0 | 20 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| l1Multicall | address | 121 | 0 | 20 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | +| canonicalL2FactoryAddress | address | 122 | 0 | 20 | contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator | diff --git a/test/storage/L1OrbitCustomGateway b/test/storage/L1OrbitCustomGateway new file mode 100644 index 0000000000..3debf013ae --- /dev/null +++ b/test/storage/L1OrbitCustomGateway @@ -0,0 +1,10 @@ +| Name | Type | Slot | Offset | Bytes | Contract | +|--------------------|---------------------------------------------------------------|------|--------|-------|--------------------------------------------------------------------------------------| +| counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | +| router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | +| inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | +| redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | +| l1ToL2Token | mapping(address => address) | 4 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | +| owner | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | +| whitelist | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | +| _status | uint256 | 7 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway | diff --git a/test/storage/L1OrbitERC20Gateway b/test/storage/L1OrbitERC20Gateway new file mode 100644 index 0000000000..64acd3ba5c --- /dev/null +++ b/test/storage/L1OrbitERC20Gateway @@ -0,0 +1,10 @@ +| Name | Type | Slot | Offset | Bytes | Contract | +|----------------------|---------------------------------------------------------------|------|--------|-------|------------------------------------------------------------------------------------| +| counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | +| router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | +| inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | +| redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | +| cloneableProxyHash | bytes32 | 4 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | +| l2BeaconProxyFactory | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | +| whitelist | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | +| _status | uint256 | 7 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway | diff --git a/test/storage/L1OrbitGatewayRouter b/test/storage/L1OrbitGatewayRouter new file mode 100644 index 0000000000..0d0a2206fe --- /dev/null +++ b/test/storage/L1OrbitGatewayRouter @@ -0,0 +1,9 @@ +| Name | Type | Slot | Offset | Bytes | Contract | +|--------------------|-----------------------------|------|--------|-------|--------------------------------------------------------------------------------------| +| whitelist | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | +| counterpartGateway | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | +| router | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | +| l1TokenToGateway | mapping(address => address) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | +| defaultGateway | address | 4 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | +| owner | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | +| inbox | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter | diff --git a/test/storage/L1OrbitReverseCustomGateway b/test/storage/L1OrbitReverseCustomGateway new file mode 100644 index 0000000000..d6b240349e --- /dev/null +++ b/test/storage/L1OrbitReverseCustomGateway @@ -0,0 +1,10 @@ +| Name | Type | Slot | Offset | Bytes | Contract | +|--------------------|---------------------------------------------------------------|------|--------|-------|----------------------------------------------------------------------------------------------------| +| counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | +| router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | +| inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | +| redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | +| l1ToL2Token | mapping(address => address) | 4 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | +| owner | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | +| whitelist | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | +| _status | uint256 | 7 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol:L1OrbitReverseCustomGateway | diff --git a/test/storage/L1OrbitUSDCGateway b/test/storage/L1OrbitUSDCGateway new file mode 100644 index 0000000000..6b669ff529 --- /dev/null +++ b/test/storage/L1OrbitUSDCGateway @@ -0,0 +1,12 @@ +| Name | Type | Slot | Offset | Bytes | Contract | +|--------------------|---------------------------------------------------------------|------|--------|-------|----------------------------------------------------------------------------------| +| counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | +| router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | +| inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | +| redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | +| l1USDC | address | 4 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | +| l2USDC | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | +| owner | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | +| burner | address | 7 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | +| depositsPaused | bool | 7 | 20 | 1 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | +| burnAmount | uint256 | 8 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol:L1OrbitUSDCGateway | diff --git a/test/storage/L1TokenBridgeRetryableSender b/test/storage/L1TokenBridgeRetryableSender new file mode 100644 index 0000000000..2233e30abe --- /dev/null +++ b/test/storage/L1TokenBridgeRetryableSender @@ -0,0 +1,7 @@ +| Name | Type | Slot | Offset | Bytes | Contract | +|---------------|-------------|------|--------|-------|----------------------------------------------------------------------------------------------| +| _initialized | uint8 | 0 | 0 | 1 | contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol:L1TokenBridgeRetryableSender | +| _initializing | bool | 0 | 1 | 1 | contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol:L1TokenBridgeRetryableSender | +| __gap | uint256[50] | 1 | 0 | 1600 | contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol:L1TokenBridgeRetryableSender | +| _owner | address | 51 | 0 | 20 | contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol:L1TokenBridgeRetryableSender | +| __gap | uint256[49] | 52 | 0 | 1568 | contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol:L1TokenBridgeRetryableSender | diff --git a/test/storage/L1USDCGateway b/test/storage/L1USDCGateway new file mode 100644 index 0000000000..bf0aacf6c2 --- /dev/null +++ b/test/storage/L1USDCGateway @@ -0,0 +1,12 @@ +| Name | Type | Slot | Offset | Bytes | Contract | +|--------------------|---------------------------------------------------------------|------|--------|-------|------------------------------------------------------------------------| +| counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | +| router | address | 1 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | +| inbox | address | 2 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | +| redirectedExits | mapping(bytes32 => struct L1ArbitrumExtendedGateway.ExitData) | 3 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | +| l1USDC | address | 4 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | +| l2USDC | address | 5 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | +| owner | address | 6 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | +| burner | address | 7 | 0 | 20 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | +| depositsPaused | bool | 7 | 20 | 1 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | +| burnAmount | uint256 | 8 | 0 | 32 | contracts/tokenbridge/ethereum/gateway/L1USDCGateway.sol:L1USDCGateway | diff --git a/test/storage/L2AtomicTokenBridgeFactory b/test/storage/L2AtomicTokenBridgeFactory new file mode 100644 index 0000000000..55eed362d4 --- /dev/null +++ b/test/storage/L2AtomicTokenBridgeFactory @@ -0,0 +1,2 @@ +| Name | Type | Slot | Offset | Bytes | Contract | +|------|------|------|--------|-------|----------| diff --git a/test/storage/L2USDCGateway b/test/storage/L2USDCGateway new file mode 100644 index 0000000000..fd55fa036c --- /dev/null +++ b/test/storage/L2USDCGateway @@ -0,0 +1,10 @@ +| Name | Type | Slot | Offset | Bytes | Contract | +|--------------------------|---------|------|--------|-------|------------------------------------------------------------------------| +| counterpartGateway | address | 0 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | +| router | address | 1 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | +| exitNum | uint256 | 2 | 0 | 32 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | +| l1USDC | address | 3 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | +| l2USDC | address | 4 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | +| owner | address | 5 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | +| usdcOwnershipTransferrer | address | 6 | 0 | 20 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | +| withdrawalsPaused | bool | 6 | 20 | 1 | contracts/tokenbridge/arbitrum/gateway/L2USDCGateway.sol:L2USDCGateway | diff --git a/test/unused-errors/exceptions.txt b/test/unused-errors/exceptions.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/yarn.lock b/yarn.lock index a33ede27d2..4feb506a0b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,14 +17,15 @@ "@openzeppelin/contracts-upgradeable" "4.5.2" patch-package "^6.4.7" -"@arbitrum/sdk@^3.1.3": - version "3.1.9" - resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.1.9.tgz#a511bc70cdd0a947445e4e27833c242ccb77ddf5" - integrity sha512-7Rf75cKmQ8nutTV+2JAOXcI6DKG4D7QCJz1JL2nq6hUpRuw4jyKn+irLqJtcIExssylLWt3t/pKV6fYseCYKNg== +"@arbitrum/sdk@^3.5.1": + version "3.5.1" + resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.5.1.tgz#9606b726101e62ca32953386a9ba341041e40c47" + integrity sha512-UQ5nUSmvFzEYpAbf1CKkYZmGGq9WysRASOWEAimc63EYVwkOV31hU5m8Dnj6JiJtLcO8mFYnTlVsJGex5oxntw== dependencies: "@ethersproject/address" "^5.0.8" "@ethersproject/bignumber" "^5.1.1" "@ethersproject/bytes" "^5.0.8" + async-mutex "^0.4.0" ethers "^5.1.0" "@babel/code-frame@7.12.11": @@ -915,6 +916,11 @@ resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.6.tgz#d11cb063a5f61a77806053e54009c40ddee49a54" integrity sha512-+Wz0hwmJGSI17B+BhU/qFRZ1l6/xMW82QGXE/Gi+WTmwgJrQefuBs1lIf7hzQ1hLk6hpkvb/zwcNkpVKRYTQYg== +"@offchainlabs/stablecoin-evm@1.0.0-orbit-alpha.2": + version "1.0.0-orbit-alpha.2" + resolved "https://registry.yarnpkg.com/@offchainlabs/stablecoin-evm/-/stablecoin-evm-1.0.0-orbit-alpha.2.tgz#1156ab9436d0791739b56b355d7cff2e3aadaede" + integrity sha512-g9SO/KD4QoIA5Mvo+wE7GDe3PwNtQ0IK3b+RNRClHKH2if4emneQtEj/eD0Tc32BuYzPRK5cbd4/lBjARo9izQ== + "@offchainlabs/upgrade-executor@1.1.0-beta.0": version "1.1.0-beta.0" resolved "https://registry.yarnpkg.com/@offchainlabs/upgrade-executor/-/upgrade-executor-1.1.0-beta.0.tgz#c4b1375176546a18aaef01a43956abfb58250e0a" @@ -1953,6 +1959,13 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== +async-mutex@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.4.1.tgz#bccf55b96f2baf8df90ed798cb5544a1f6ee4c2c" + integrity sha512-WfoBo4E/TbCX1G95XTjbWTE3X2XLG0m1Xbv2cwOtuPdyH9CZvnaA5nCt1ucjaKEgW2A5IF71hxrRhr83Je5xjA== + dependencies: + tslib "^2.4.0" + async@1.x, async@^1.4.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -9733,6 +9746,11 @@ tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.4.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== + tslint@^6.1.3: version "6.1.3" resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904"